개발 환경


1. OS 환경

- macOS Sierra (버전 10.12.6)


2. STS (Spring Tool Suite)

스프링 애플리케이션 개발을 위한 이클립스 기반 개발 환경

- Maven, Git, Gradle, AspectJ 와 연동 가능


3. Apache Tomcat 8.5 

- jsp, servlet, class, EJB 등을 실행시키는 웹 컨테이너 

- 웹서버의 기능도 포함


* STS와 톰캣 설치 방법 : [Spring Framework 세팅하기1 - 설치] 글 참고


Spring Boot 

  • 기존 SpringMVC 프로젝트에서 xml을 통해 설정하던 것들을 자동으로 셋업하여 만들어놓은 스프링 서브 프로젝트
  • STS 에서 프로젝트 생성할 때, spring legacy~로 생성하면 SpringMVC, spring starter~로 생성하면 SpringBoot 프로젝트이다!


프로젝트 생성 순서

1. 프로젝트 생성하기

STS 상단 메뉴 > File > New > Spring Starter Project 


2. 프로젝트 정보 입력

Name : 프로젝트 이름

Type : Gradle 또는 Maven 선택 (여기에서는 Gradle 선택)

Group, Package : 패키지 명





3. dependency 설정 


지금은 테스트 프로젝트이므로 간단하게 추가 > 더 추가하려면 검색 > Finish 클릭 

  • Security
  • Aspects
  • JPA
  • MySQL
  • H2
  • JDBC
  • Web





4. 웹페이지 테스트를 위한 Controller 추가


프로젝트 > com.bbchu.demo 패키지 선택 > 우클릭 > New > Class 선택 > TestController.java 생성


루트(/) 요청이 들어왔을 때 root 메소드로 매핑 


package com.bbchu.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	
	@RequestMapping("/")
	public String root()
	{
		return "Spring Boot Test";
	}
	
}


5. 테스트 

 

  • 톰캣 기본 포트는 8080이므로 http://localhost:8080/프로젝트이름/ 접속 
  • Server 탭에 톰캣 더블클릭 > Modules 탭 > Edit > Path 를 / 로 설정 시, url 에 프로젝트이름 생략 가능 (Context Root 를 / 로 지정)






** 이슈 : 실행 시 로그인 화면이 뜬다면 build.gradle 파일에서 security 주석처리


//compile('org.springframework.boot:spring-boot-starter-security')









자바 문자열 객체

  • String
  • StringBuffer
  • StringBuilder


String 객체

String 객체는 new 연산을 이용해서 객체를 생성하면 인스턴스의 메모리 공간이 변하지 않는다. (immutable)
따라서, + 연산이나 concat을 수행하면 새로운 문자열 객체들이 만들어지고
이를 반복하면 새로운 인스턴스들이 생겨나므로 성능이 낮아진다. 

메모리값이 변하지않으므로 조회 연산에서는 다른 클래스보다 성능이 좋고
그렇기때문에 멀티스레드 환경에서 동기화에 대해 신경쓸 필요가 없다.

> String 객체는 문자열 연산이 적고, 조회가 많은 멀티스레드 환경에 적합


StringBuffer, StringBuilder 객체

String 과 다른 점은 mutable 하다는 점이다.
문자열을 생성하고(new) 변경사항이 생기면 메모리 크기를 늘려서 문자열을 바꾼다.

StringBuffer 와 StringBuilder 는 내부적으로 메소드가 동일하지만
StringBuffer 는 동기화를 지원(syncronized)하고 StringBuilder 는 동기화를 지원하지 않는다는 점에서 다르다.

따라서 멀티스레드 환경에서는 StringBuffer 를 사용하고(thread-safe)
싱글스레드 환경에서는 StringBuilder 를 사용하여 연산속도를 빠르게 하는 것이 적합하다.

> 문자열 연산이 많고 멀티스레드이면 StringBuffer를, 동기화를 신경쓸 필요가 없다면 StringBuildrer 사용


JDK 버전에 따른 String 성능 개선

1.5 버전 이상에서는
String 객체로 연산해도 내부적으로 StringBuilder 로 변환되어 성능상 이슈를 해결했다고 한다.



'Language > Java' 카테고리의 다른 글

자바 커뮤니티2 - 상속  (0) 2019.05.28
자바 커뮤니티1 - Class  (0) 2019.05.22
Java 배열 선언, 초기화  (0) 2018.08.04
Java 접근지정자 (Access Modifier)  (0) 2018.08.04
Java String Constant Pool의 이해  (0) 2018.08.02

배열 선언


int[] num;



배열 생성


num = {1, 2, 3};
num = new int[3];
num = new int[] {1, 2, 3};



메모리 계산


int[] num = new int[10];


int(4byte) * 10 => 40 byte



배열 초기화


int num[] = new int[] {1, 2, 3};
int num[] = {1, 2, 3};


'Language > Java' 카테고리의 다른 글

자바 커뮤니티1 - Class  (0) 2019.05.22
Java 문자열 객체  (0) 2018.08.04
Java 접근지정자 (Access Modifier)  (0) 2018.08.04
Java String Constant Pool의 이해  (0) 2018.08.02
Comparator 인터페이스를 이용한 다중 정렬  (0) 2018.08.01

접근지정자 (Access Modifier) 종류

  • public
  • protected
  • default (아무 키워드도 안붙인 상태)
  • private

public > protected > default > private 순으로 접근 범위


범위

 

 범위

 같은 클래스 내

같은 패키지 내 

 다른 패키지의 

자식클래스

다른 패키지 

 public

 접근 제한 없음

 O

O

O

 protected

 같은 패키지나 클래스

상속받은 클래스

 O

O

O

 

 default

같은 클래스나 패키지 

 O

O

 

 

 private

같은 클래스에서만 

 O

 

 

 



public

접근에 제한이 없다.

protected

같은 패키지 내에서 접근 가능하고
다른 패키지이더라도 상속받은 경우는 클래스 내부에서 접근 가능하다.
but, 다른 패키지 외부에서는 접근 불가능하다.

default

변수나 메소드 선언에 아무 키워드도 붙이지 않은 접근 범위이다.
같은 클래스나 패키지 안에서만 접근 가능하다.

private 

같은 클래스 내부에서만 접근 가능하다.

'Language > Java' 카테고리의 다른 글

자바 커뮤니티1 - Class  (0) 2019.05.22
Java 문자열 객체  (0) 2018.08.04
Java 배열 선언, 초기화  (0) 2018.08.04
Java String Constant Pool의 이해  (0) 2018.08.02
Comparator 인터페이스를 이용한 다중 정렬  (0) 2018.08.01

String Constant Pool의 이해


우연히 생활코딩에서 보게 된 글, 답은 당연히 false 라고 생각했지만 직접 돌려본 결과 true였다.

// true일까요 false 일까요?

String a = "aaa";
String b = "aaa";
if (a == b) {
    System.out.println("true");
} else {
    System.out.println("false");
}

[예제1] 객체 비교 문제



== 연산


Java 에서 == 연산은 객체의 주소값을 비교할 때 사용하고 

문자열의 값을 비교할 때는 equals 함수를 쓴다.


그런데 [예제1] 에서는 ==연산으로 비교했음에도 결과값은 왜 true를 반환할까



String Constant Pool 


답은 String Constant Pool 때문이었다.


먼저 String을 생성하는 방법은 대표적으로 2가지가 있다.

  1. new 연산자 방식
  2. literal을 이용한 방식


String a = new String("aaa"); // new 방식
String b = "aaa"; // literal 방식

[예제2] String 선언 방식



literal 로 String 을 선언한 경우 


String 객체는 내부적으로 intern() 메소드를 호출하게 된다.

intern 메소드는 String Constant Pool 에서 해당 문자열이 존재하는지 검색하고

존재하면 해당 문자열의 주소값을 반환

존재하지 않으면 새로운 주소값을 할당하여 반환한다.


이러한 동작원리에 따라 [예제1] 의 결과값은 true를 반환한다.



intern 메소드


명시적으로 intern 메소드를 호출하면 어떤 결과가 나올지 테스트해보았다.

String a = new String("aaa"); 
String b = "aaa"; 
String c = a.intern();

System.out.println(a == b); // false
System.out.println(b == c); // true


new 연산자로 선언한 a 와 literal 로 선언한 b 객체의 주소값은 다르지만

b와 a의 intern 메소드를 호출한 주소값(c)은 같았다.


따라서 literal 로 생성한 문자열은 스트링풀에 등록되고 내부적으로 고유의 인스턴스를 공유하는 것을 알 수 있다.



String Constant Pool 위치


Java6에서 스트링풀은 Perm 영역에 있었는데 

OutOfMemory(OOM) 문제로 Java7에서는 Heap 영역으로 변경되었다고 한다.


Perm 영역은 고정되어있고 Runtime 시에도 확장되지 않기때문에 Java6 이하 버전에서 intern 메소드를 자주 호출하면 OOM이 발생할 수 있다.



Heap 영역으로 변경 후 이점


Heap 영역으로 변경된 후 스트링 풀에 있는 문자열도 GC 대상이 된다.

따라서 효율적인 메모리 관리가 가능해진다.



스트링 풀 사이즈 설정


  • 스트링풀 사이즈는 -xx:StringTableSize 옵션으로 설정이 가능하다. (디폴트 : 1009)
  • intern 메소드를 자주 사용한다면 사이즈는 디폴트 값보다 높게 설정해야한다.
  • 사이즈 값으로는 소수를 사용해야 한다. (예를 들면 1,000,003)






참고 : https://medium.com/@joongwon/string-%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0-57af94cbb6bc

'Language > Java' 카테고리의 다른 글

자바 커뮤니티1 - Class  (0) 2019.05.22
Java 문자열 객체  (0) 2018.08.04
Java 배열 선언, 초기화  (0) 2018.08.04
Java 접근지정자 (Access Modifier)  (0) 2018.08.04
Comparator 인터페이스를 이용한 다중 정렬  (0) 2018.08.01

자바에서 객체를 특정 기준으로 정렬하는 경우 Comparable이나 Comparator 인터페이스를 사용



(예제)Comparator 인터페이스를 이용한 다중 정렬

  1. Board 객체를 생성
  2. Comparator 인터페이스를 구현한 MultiComp 클래스 정의
  3. MultiComp 클래스를 이용해 Board 객체 정렬

조건
  • cnt 내림차순
  • cnt 가 같은 경우 date 의 최신순서로 정렬 (내림차순)


Board 객체를 생성

  • date 형식 : 20180801
public class Board {
    int cnt;
    String date;
}

[예제1] Board 객체



Comparator 인터페이스를 구현한 MultiComp 클래스 정의


조건1. cnt 내림차순

조건2. cnt 가 같은 경우 date 의 최신순서로 정렬 (내림차순)

import java.util.Comparator; import com.Board; public class MultiComp implements Comparator< Board > { public MultiComp() { super(); } @Override public int compare(Board o1, Board o2) { int c1 = o1.getCnt(); int c2 = o2.getCnt(); if (c1 < c2) { return 1; } else if (c1 > c2) { return -1; } else { // c1 == c2 // (-1) 내림차순을 위한 부호 변환 return (-1) * (o1.getDate().compareTo(o2.getDate())); } }

[예제2] MultiComp 클래스



MultiComp 클래스를 이용해 Board 객체 정렬

  • Collections.sort 함수를 이용하여 객체 정렬

List< Board> resultList = new ArrayList< Board >();
resultList = db.getXXX(); // DB에서 데이터 가져오기
Collections.sort(resultList, new MultiComp());

'Language > Java' 카테고리의 다른 글

자바 커뮤니티1 - Class  (0) 2019.05.22
Java 문자열 객체  (0) 2018.08.04
Java 배열 선언, 초기화  (0) 2018.08.04
Java 접근지정자 (Access Modifier)  (0) 2018.08.04
Java String Constant Pool의 이해  (0) 2018.08.02

Scope 란?

scope 는 범위라는 뜻으로 프로그래밍 언어에서 변수나 메소드의 참조 범위

여기에서는 javascript 에 대한 scope 개념만 설명


Scope 종류

전역(global scope) : script 내에 어느 곳에서든 참조 가능

지역(local scope) : 정의된 함수 내에서만 참조 가능. 함수 외부에서는 접근 불가


[ 사진1 ] JavaScript 의 Scope 종류



> 로컬 변수의 값을 바꾸더라도 함수 내부에서만 유효하므로 전역변수의 값은 바뀌지 않음

var x = 'global';
function ex() {
  var x = 'local';
  x = 'change';
}
ex(); // x를 바꿔본다.
alert(x); // 여전히 'global'

[ 예제1 ] 지역/전역 변수 특징



JavaScript의 Scope 특징

  • 변수명 중복 허용
  • var 키워드 생략
  • Function Scope
  • 렉시컬 특성
  • 변수 호이스팅 (variable hoisting)



변수명 중복 허용

자바스크립트에서는 변수명이 중복되어도 에러가 나지 않음

변수명이 여러 개 중복될 경우 가장 가까운 변수를 참조


var scope = 10;  
function scopeExam(){  
    var scope = 20;
    console.log("scope = " +scope);
}
scopeExam();  
//실행결과
/*
scope =20  
*/

[ 예제2 ] 변수명 중복 허용



var 키워드 생략

var 키워드를 붙이지 않으면 전역변수로 정의


> 전역 변수는 어디에서나 참조 가능하므로 변경된 값으로 출력

var x = 'global';
function ex() {
  x = 'change';
}
ex();
alert(x); // 'change'

[ 예제3 ] var 키워드 생략



Function Scope

자바스크립트는 블록단위가 아닌 함수 단위로 scope를 정의



> 다른 프로그래밍 언어는 블록 단위로 변수의 scope 가 정의

> 자바스크립트의 경우 function scope 의 특징을 가지므로 함수 내에서 a, b, c 의 scope 가 동일

function scopeTest() {  
    var a = 0;
    if (true) {
        var b = 0;
        for (var c = 0; c < 5; c++) {
            console.log("c=" + c);
         }
         console.log("c=" + c);
    }
    console.log("b=" + b);
}
scopeTest();  
//실행결과
/*
c = 0  
c = 1  
c = 2  
c = 3  
c = 4  
c = 5  
b = 0  
*/

[ 예제4 ] Function Scope 특징



렉시컬 특성

스코프는 함수 실행 시점이 아닌 정의 시점에 생성

lexical scoping, 정적 스코프라고도 불림



> f2 가 f1 안에서 실행되었지만 f2 외부에 있는 변수 a 를 호출할 수는 없음

function f1(){  
    var a= 10;
    f2();
}
function f2(){  
    return console.log("호출 실행");
}
f1();

//실행결과
/*

호출실행
*/
function f1(){  
    var a= 10;
    f2();
}
function f2(){  
    return a;
}
f1();

//실행결과
/*
Uncaught Reference Error  
: a is not defined
*/

[ 예제5 ] Lexical Scoping



변수 호이스팅 (variable hoisting)

변수의 정의가 선언과 할당으로 분리되는 것을 의미

변수가 함수 내에서 정의되었을 경우 선언이 함수의 최상단으로 이동

변수가 전역에서 정의된 경우 전역 컨텍스트의 최상단으로 이동

호이스팅은 함수 선언 방식에만 적용 가능 

(함수표현식, Function 생성 방식은 함수 변수로 인식)



> 예제6 소스는 자바스크립트 엔진에 의해 예제 7처럼 동작 (name 변수가 호이스팅)

function doSomething() {
    console.log("value : " + name);
    var name = "bbchu";
    console.log("value : " + name);
}
doSomething();

//실행결과
/*
undefined
bbchu
*/

[ 예제6 ] Variable Hoisting

function doSomething() {
    var name;
    console.log("value : " + name);
    name = "bbchu";
    console.log("value : " + name);
}
doSomething();

//실행결과
/*
undefined
bbchu
*/

[ 예제7 ] Variable Hoisting






'Language > JavaScript' 카테고리의 다른 글

ECMAScript  (0) 2019.09.24

M/M (Man/Month) 란?

 

한 명의 능력을 100%,

 

연간 일하는 기간을 12개월로 정한 후프로젝트에 투입되는 인력을 나타내는 숫자 개념을 말합니다.

 

 

 

M/M 산정 방식

 

(참여율 * 참여기간)

 

한달 영업일 기준 : 22일

 

 

 

M/M 예시

 

인원 기준

참여율

참여기간

M/M 계산 결과

1명

100%

한달

1M/M  

1명

20%

1년

2.4M/M 

1명

50%

3개월

1.5M/M 

 

 

 

'프로젝트 관리 툴 > 기타' 카테고리의 다른 글

Mac 터미널 명령어  (0) 2019.01.22
빌드툴 - Gradle과 Maven  (0) 2018.08.31

Python 이란?

  • 1990년 암스테르담의 귀도 반 로섬(Guido Van Rossum)이 개발한 인터프리터(Interpreter) 언어
  • 고대 신화에 나오는 파르나소스 산의 동굴에 살던 큰 뱀 (파이썬 표지와 아이콘이 뱀 모양)
  • 다양한 라이브러리들과 통합환경의 동시 제공 (numpy, pandas 등)
  • 관련 서비스 

- 파일 동기화 서비스 드롭박스(Dropbox)

- Web 개발 프레임워크 장고(Django/Flask)

- 머신러닝/딥러닝 라이브러리(Sklearn, tensorflow, mxnet, pytorch..)



Python 특징

  • Interpreter 기반의 객체 지향 언어

- 바이트 코드 컴파일을 지원하는 동적 인터프리팅 언어 (.py > .pyc)

- python shell 에서 interpreter 모드 테스트 가능


  •  플랫폼 독립적 언어

- Windows, MAC OS, Palm OS, Android, Unix 계열, Linux 계열 등 다양한 OS 지원


  •  유연한 확장

- 컴파일된 외부 모듈을 인터프리터 내부로 동적로딩 지원


  •  동적 타이핑

- 컴파일 시점이 아닌 프로그램 실행 시점에 Type Checking 을 수행

- 개발생산성 향상 가능

- 디버그 속도 저하 발생 가능


  •  리플렉션 (Reflection)

- Runtime 시 객체에 대한 상세 정보 획득 가능

- Object Properties 조작 가능


  •  쉬운 문법, 빠른 속도

- 프로그램의 뼈대는 파이썬으로 짜고 빠른 실행속도를 필요로 하는 부분은 C 로 구현하여 import 가능

- Python 의 많은 라이브러리가 C 로 구현됨


  •  간결함

- { } (브레이스) 없이 들여쓰기를 통해 단락 구분

- 강제적인 인덴테이션으로 가독성 향상



OOP - Classes and Instances


  • 일반적인 클래스 정의

class Employee:
    pass # do nothing

emp_1 = Employee()
emp_2 = Employee() # emp_1, emp2는 클래스(Employee)의 인스턴스, 주소 다름

 

  • 인스턴스 변수 설정

emp_1.first = "kildong"
emp_1.last = "hong"
emp_1.email = "kildong.hong@gmail.com"
emp_1.pay = 100


  • 설정 값 확인

print('{} / {}'.format(emp_1.email, emp_1.first))



Class Variables  클래스 변수


  • 클래스 전역 변수

- cls 지시자를 통해 access 가능


  • 인스턴스 변수는 self 지시자를 통해 access


class Employee:
    raise_amount = 1.04

    def __init__(self, first, last, pay):
        self.first = first
        self.last = last
        self.pay = pay
        self.email = first + '.' + last + '@email.com'

emp_1 = Employee('killdong', 'hong', 10000)
emp_2 = Employee('chunhang', 'sung', 2000)

# raise_amount - 클래스 변수
# first, last, pay, email - 인스턴스 변수


// 클래스 변수 값을 변경하면 해당 인스턴스의 값이 전부 변경된다.
Employee.raise_amount = 1.05

print(emp_1.raise_amount)             # 1.05
print(emp_2.raise_amount)            # 1.05
print(Employee.raise_amount)       # 1.05

// 인스턴스 변수에 대한 값을 변경하면 클래스 변수의 raise_amount 는 바뀌지 않는다.
emp_1.raise_amount = 1.06

print(emp_1.raise_amount)         # 1.06
print(emp_2.raise_amount)        # 1.05
print(Employee.raise_amount)   # 1.05



Static Method and Class Method


  • Instance Method

- 일반적인 메소드 형태

- parameter 는 self 부터 시작 (instance 의미)


  • Class Method

- @classmethod annotation 으로 접근가능

- parameter 는 cls 부터 시작 (class 의미)


  • Static Method

- @staticmethod annotation 으로 접근가능

- method parameter 에 self, cls 없음

- util 성 메소드 작성에 적합

- class, instance를 통해서 접근 가능하나 되도록 class 를 통해 호출하는 것이 바람직


class Employee:
    
    raise_amount = 1.04 
    num_of_emps  = 0   ### instance개수를 담을 class variables
    
    def __init__(self, first, last, pay):
        self.first = first
        self.last  = last
        self.pay   = pay
        self.email = first + '.' + last + '@email.com'
        
        Employee.num_of_emps += 1 ## instance개수를 +1씩 증가시킨다.
        
        
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
    def apply_raise(self):
        self.pay = int(self.pay * self.raise_amount) #Instance Variables는 'self.변수명'으로 접근 가능
        
    # class method선언은 @classmethod annotation을 사용하고
    # 메소드 파라미터의 첫인자는 cls를 기본적으로 설정한다.
    @classmethod
    def set_raise_amt(cls, amount):
        cls.raise_amount = amount
        
    @classmethod
    def from_string(cls, emp_str):
        first, last, pay = emp_str.split('-')
        #return Employee(first, last, pay) # __init__ parameter와 같은 순서로 객체를 생성하라.
        return cls(first, last, pay)
    
    #static method는 별도의 parameter를 전달하지 않는다.
    # weekday()는 '0:월, 1:화, 2:수, 3:목, 4:금, 5:토, 6:일'의 값을 리턴
    @staticmethod
    def is_workday(day):
        if day.weekday() == 5 or day.weekday() == 6:
            return False
        return True

# class method를 통해서 class variables를 변경한다.
Employee.set_raise_amt(1.05)

# class method를 통한 instance 생성
new_emp_1 = Employee.from_string(emp_str_1)
new_emp_2 = Employee.from_string(emp_str_2)

#static method 호출 > class를 통해 접근
import datetime
my_date = datetime.date(2016, 7, 11)
print(Employee.is_workday(my_date))

# instance를 통해서도 호출은 가능하나, class를 통해서 호출하는 것이 바람직.
new_emp_1.is_workday(datetime.date(2018, 6, 2))



Inheritance-Subclasses

  •  부모 클래스의 속성/메소드와 같은 속성/메소드를 자식 클래스에서 재정의 가능


class Employee:
    
    raise_amount = 1.04 
     
    def __init__(self, first, last, pay):
        self.first = first
        self.last  = last
        self.pay   = pay
        self.email = first + '.' + last + '@email.com'
        
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
    def apply_raise(self):
        self.pay = int(self.pay * self.raise_amount) #Instance Variables는 'self.변수명'으로 접근 가능

#Employee를 상속하는 자식클래스를 선언
class Developer(Employee):
    raise_amount = 1.10
    
    def __init__(self, first, last, pay, prog_lang):
        #부모 클래스의 메소드를 실행한다.
        super().__init__(first, last, pay)
        #Employee.__init__(first, last, pay) #이 코드도 상위 클래스 __init__ call
        self.prog_lang = prog_lang

dev_1 = Developer('kildong', 'hong', 10000000) # Java와 달리 new keyword를 사용하지 않음.
dev_2 = Developer('sunghun', 'kim', 5000000) # emp_1(객체)는 클래스(Employee)의 인스턴스(Instance)이다.

#자식클래스가 부모 클래스의 속성과 메소드를 상속하여 정상 동작함.
print(dev_1.email)
print(dev_2.email)

# Employee 를 상속하는 Manager 클래스
class Manager(Employee):    
    #parameter=None은 해당 parameter가 값이 없을 경우 None으로 설정한다.(default value)
    def __init__(self, first, last, pay, employees=None):
        #부모 클래스의 메소드를 실행한다.
        super().__init__(first, last, pay)
        if employees is None:
            self.employees = []
        else:
            self.employees = employees

    #부모 클래스에 없는 메소드 정의 가능    
    def add_emp(self, emp):
        if emp not in self.employees:
            self.employees.append(emp) #list append
            
    def remove_emp(self, emp):
        if emp in self.employees:
            self.employees.remove(emp) #list remove
            
    def print_emps(self):
        for emp in self.employees:
            print('-->{}'.format(emp.fullname()))



Instance Type / Subclass 여부 확인

print(isinstance(mgr_1, Manager))        #True
print(issubclass(Developer, Employee))    #True
print(issubclass(Employee, Manager))      #False



다중상속

  • python은 다중상속을 지원하므로 instance 키워드가 없음
class parentA:
    
    def print(self):
        print('parentA')
        
    def printA(self):
        print('parentA print')
        
class parentB:
    def print(self):
        print('parentB')
        
    def printB(self):
        print('parentB print')
        
class Child(parentA, parentB):
    def print(self):
        super().print()
        print('child C')

ins = Child()
ins.print() # 다중 상속 클래스의 선언된 순서에서 우선한 것의 메소드를 실행한다.
ins.printB()
ins.printA()




 float 속성

  • '띄우다'라는 의미로 원래는 이미지와 텍스트를 어떻게 정렬할 것인지에 대한 속성
  • 현재는 레이아웃용으로도 많이 사용
  • block level element 에만 float 속성을 사용할 수 있다.
  • 속성값

 left

  앨리먼트를 왼쪽에 배치하고 나머지 앨리먼트를 오른쪽에 배치. 페이지 흐름이 위에서 아래

 right

  앨리먼트를 오른쪽에 배치하고 나머지 앨리먼트를 왼쪽에 배치. 페이지 흐름이 위에서 아래

 inherit

  부모로부터 float 속성 상속

 none

  지정하지 않음




clear 속성

  • '취소하다'의 뜻으로 float 속성의 페이지 흐름을 변경
  • 속성값

left

 float:left 인 앨리먼트에 대해 주변 앨리먼트가 영향을 받지 않도록 설정

 right

 float:right 인 앨리먼트에 대해 주변 앨리먼트가 영향을 받지 않도록 설정

 both

 양쪽 float 속성인 앨리먼트에 대해 주변 앨리먼트가 영향을 받지 않도록 설정

 inherit

 부모로부터 clear 속성 상속

 none

 지정하지 않음


'Language > CSS' 카테고리의 다른 글

CSS 개념 - flex  (0) 2018.05.31
CSS 기본 문법1  (0) 2018.05.17

+ Recent posts