Chapter 2. 객체지향 프로그래밍 II
1. 상속(Inheritance)
- 기존에 존재하는 Class를 재사용하여 새로운 Class를 작성하는 것
- 장점
· 보다 적은 양의 Code로 새로운 Class를 작성할 수 있다.
· Code를 공통적으로 관리할 수 있어 Code의 추가, 변경을 편하게 할 수 있다.
· Code의 재사용성을 높이고 Code의 중복을 제거해 Program의 생산성과 유지보수에 도움을 준다.
- Class 계층
· Class끼리의 상속 관계에서는 부모 Class와 자식 Class 관계가 존재한다.
· 자식 Class에서는 부모 Class의 변수나 Method에 접근할 수 있지만 부모 Class에서는 자식 Class의 변수나 Method에 접근할 수 없다.
· 자식 Class에 추가적인 Code가 발생해도 부모 Class는 영향을 받지 않는다.
· 자식 Class가 부모 Class를 상속 받을 때 생성자와 초기화 Block은 상속 받지 않는다.
· 한 부모 Class는 여러 자식 Class에 상속해줄 수 있다.
· 이미 한 번 상속 받은 적 있는 자식 Class도 부모 Class가 되어 또 다른 자식 Class에 상속해줄 수 있다.
· 부모(Parent) Class
◦ 상속 관계에서 상속해주는 Class
◦ 상속을 해주는 입장이기 때문에 자식 Class 변수 및 Method 수가 적거나 같을 수 있다.
◦ 같은 용어
▹ 조상(Parent) Class
▹ 상위(Super) Class
▹ 기반(Base) Class
· 자식 Class
◦ 상속 관계에서 상속받는 Class
◦ 상속을 받는 입장으로 부모 Class의 변수 및 Method를 모두 사용할 수 있으며 그 외에 추가적인 변수나 Method가 존재할 수 있다.
◦ 같은 용어
▹ 자손(Child) Class
▹ 하위(Sub) Class
▹ 파생된(Derived) Class
- 상속 Class 구현 방법
1 2 3 | class [Child] extends [Parent] { …… } | cs |
- 여러 상속 관계에 있는 여러 Class의 구조 예
- Class 간의 관계
· 포함관계
1 2 3 | class Composite { IncludeFactor IF = new IncludeFactor(); } | cs |
◦ Instance 변수를 이용해 포함하는 방법
◦ 작성된 단위 Class 별로 Code가 나뉘어 보다 관리하기 쉽다.
· 상속관계
1 2 3 4 5 6 7 | class Child extends Parent { int z; } class Parent { int x; int y; } | cs |
◦ 상속(extend)을 이용해 Class를 구성하는 방법
· 포함관계와 상속관계를 구분하는 방법
◦ 포함관계
▹ ~은 –이다.
▹ ~ is a -
◦ 상속관계
▹ ~은 –을 가지고 있다.
▹ ~ has a -
- 단일 상속(Single Inheritance)
· 자식Class가 상속받을 때 하나의 부모 Class에게만 상속받는 것
· C++에서는 다중 상속을 제공해 하나의 자식 Class가 여러 부모 Class를 상속 받을 수 있었는데 이 다중 상속이 상속 구조를 복잡하게 해 Java에서는 다중상속을 제공하지 않는다.
· 다중상속을 제공하지 않음으로 인해 Class간의 관계를 더 명확히 알 수 있고 Code를 더 신뢰할 수 있게 되었다.
- Object Class
· 모든 Class 상속 계층도의 최상위에 위치하는 부모 Class
· 일반적으로 다른 Class를 사용한다는 import를 이용하지 않고 사용할 수 있는 함수나 변수는 모두 Object Class 내에 존재하기 때문이다.
· Object Class는 따로 상속한다고 Code를 작성하지 않아도 상속되어 부모 Class로써 상속된다.
2. Overriding
- Overriding
· 부모 Class로부터 상속받은 Method의 내용을 변경하는 것
· 부모 Class와 자식 Class의 Overriding 조건
◦ 이름이 같아야 한다.
◦ 매개변수가 같아야 한다.
◦ Return Type이 같아야 한다.
◦ 접근 제어자는 부모 Class의 Method보다 좁은 범위로 변경할 수 없다.
◦ 부모 Class의 Method보다 많은 수의 예외를 선언할 수 없다.
- super
· 자식 Class에서 부모 Class로부터 상속 받은 Member나 Method를 상속받을 때 사용되는 참조 변수
· Member의 경우
◦ 자식 Class에서 같은 이름의 변수를 다시 정의 했고 부모 Class의 Member가 정의 되었을 경우 super을 이용해 접근할 수 있다.
· Method의 경우
◦ 자식 Class에서 Overriding해 Method의 내용을 변경했을 경우 Class의 Method가 다시 필요하게 되면 super을 통해 접근할 수 있다.
· 부모 Class 생성자 접근 – super()
◦ 생성자 내에서 다른 생성자에 접근할 때 this()를 사용하듯이 부모 Class의 생성자에 접근하기 위해서 super()를 사용한다.
◦ 자식 Class의 Instance를 생성하면 자식 Member와 부모 Member가 모두 합쳐진 하나의 Instance가 생성된다.
◦ 부모 Class의 Member가 자식 Class에서 사용될 수 있으므로 가장 먼저 초기화 하기 위해 자식 Class의 생성자 첫 줄에서 조상 Class의 생성자가 호출 되어야한다.
◦ Object Class를 제외한 모든 Class의 생성자 첫 줄에는 생성자를 호출해야하며 호출하지 않을 시 Compiler가 super();를 자동으로 추가한다.
- Compare Overloading and Overriding
· Overloading
1 2 3 4 5 6 7 8 9 10 | class Parent{ void Method() { …… } } class Child extends Parent{ void Method(int i) { …… } } | cs |
◦ Method의 이름은 같지만 매개변수는 다른 Method 즉, 새로운 Method를 정의하는 것
◦ 중복 정의라고도 한다.
· Overriding
1 2 3 4 5 6 7 8 9 10 | class Parent{ void Method() { …… } } class Child extends Parent{ void Method() { …… } } | cs |
◦ 기존에 상속 받은 Method의 내용을 변경해 사용하는 것
3. Package & Import
- Package
· Class의 묶음을 말하며 Class끼리 Group 단위로 묶어 놓아 Class를 효율적으로 관리할 수 있도록 도와준다.
· Class를 하나의 File로 비유하지면 Package는 하나의 Directory로 비유할 수 있다.
· Package의 특징
◦ 하나의 Source File에는 첫 번째 문장으로 단 한 번의 Package 선언만을 허용한다.
◦ 모든 Class는 반드시 하나의 Package에 속해야한다.
◦ Package는 점(.)을 구분자로 하여 계층 구조로 구성할 수 있다.
◦ Package는 물리적으로 Class File을 포함하는 하나의 Directory이다.
· Package 선언
1 | package [Package Name]; | cs |
◦ Package를 따로 선언하지 않으면 Unnamed Package에 속하게 되며 Package를 지정하지 않는 모든 Class는 같은 Package내에 속하게 되는 것이 된다.
- Import
· Compiler에 Source File에 사용된 Class의 Package에 대한 정보를 제공한다.
· 다른 Package의 Class를 사용하기 위해 해당 Class의 Package를 미리 명시해 Source Code에 사용되는 Class 이름에서 Package 명을 생략할 수 있다.
· import문 선언
1 2 | import [Package Name].[Class Name]; import [Package Name].*; | cs |
◦ Package 이름을 생략하고자 하는 Class의 이름을 Package 이름과 함께 써주면 된다.
4. 제어자(Modifier)
- 제어자
· Class, Variable, Method의 선언부와 함께 사용되어 부가적인 의미를 부여한다.
· 제어자 종류
◦ 접근 제어자(Access Modifier)
▹ Member 또는 Class에 사용되어 해당하는 Member 또는 Class를 외부에서 접근하지 못하도록 제한한다.
▹ 접근 제어자 접근 범위
▸ public > protected > default > private
▹ 접근 제어자 종류
▸ public
▫ 접근 제한을 없앤다.
▸ protected
▫ 같은 Class 내에서, 다른 Package의 자식 Class에서 접근이 가능하다.
▸ default
▫ 같은 Package 내에서만 접근 가능하도록 제한하다.
▫ 제어자를 아무 것도 언급하지 않는 형식
▸ private
▫ 같은 Class 내에서만 접근할 수 있도록 제한한다.
▹ Encapsulation
▸ 본질적 특성을 사용하지 않은 대상의 세부 사항을 감추는 기술로 Data Hiding이라고도 한다.
▸ 접근 제어자를 이용해 Encapsulation하는 이유
▫ 내부 : 외부로부터 Data를 보호하기 위해
▫ 외부 : 불필요한 내부적으로 사용되는 부분을 감추기 위해
▹ 생성자의 접근 제어자
▸ 생성자의 접근 제어자를 private로 지정하면 외부 Class에서 접근할 수 없어 Instance를 형성할 수 없다.
▸ private로 지정된 생성자는 Class 내부에서만 접근 가능하므로 다른 Method를 생성해 해당 생성자에 접근해아한다.
▸ private로 생성자가 선언되기 전에 Instance를 Class내부에 미리 선언해야하므로 private에 static까지 사용해 미리 생성되게 만들어 줘야한다.
▸ Example
1 2 3 4 5 6 7 8 9 | class Constr{ private static Constr c = new Constr(); private Constr() { …… } public static Constr getInstance() { return c; } } | cs |
◦ static
▹ Member Variable
▸ 모든 Instance에 공통적으로 사용되는 Class Variable가 된다.
▸ Class Variable은 Instance를 생성하지 않고 사용 가능하다.
▸ Class가 Memory에 Load될 때 생성된다.
▹ Method
▸ Instance를 생성하지 않고도 호출이 가능한 static Method가 된다.
▸ static Method 내에서는 Instance Member들을 직접 사용할 수 없다.
◦ final
▹ Class
▸ 변경될 수 없는 Class, 확장될 수 없는 Class가 된다.
▸ final로 지정된 Class는 다른 Class의 부모가 될 수 없다.
▹ Method
▸ 변경될수 없는 Method
▸ final로 지정된 Method는 Overriding을 통해 재정의 될 수 없다.
▹ Member Variable
▸ 변수 앞에 Final이 붙으면, 값을 변경할 수 없는 상수가 된다.
▹ Local Variable
▸ 변수 앞에 Final이 붙으면, 값을 변경할 수 없는 상수가 된다.
◦ abstract
▹ Class
▸ Class 내에 추상 Method가 선언되어 있음을 의미한다.
▹ Method
▸ 선언부만 작성하고 구현부는 작성하지 않은 추상 Method임을 알린다.
◦ native
◦ transient
◦ synchronized
◦ volatile
◦ strictfp
· 제어자 조합
◦ 대상에 따라 사용할 수 있는 제어자
▹ Class : public, default, final, abstract
▹ Method : public, protecte, default, private, final, abstract, static
▹ Member Variable : public, protecte, default, private, final, static
▹ Local Variable : final
◦ 제어자 조합 시 유의사항
▹ Method에 static과 abstract를 함께 사용할 수 없다.
▹ Class에 abstract와 final을 동시에 사용할 수 없다.
▹ abstract Method의 접근 제어자가 private일 수는 없다.
▹ Method에 private와 final을 같이 사용할 필요는 없다.
5. 다형성(Polymorphism)
- 다형성
· 여러 가지 형태를 가질 수 있는 성질
· Java에서 한 Type의 참조변수로 여러 Type의 객체를 참조할 수 있도록 함으로써 다형성이 구현되어 있다.
· 부모 Class Type의 참조변수로 자식 Class의 Instance를 참조할 수 있도록 구현되어 있다.
· Example
1 2 3 | Child C = new Child(); Parent P1 = new Parant(); Parent P2 = new Child(); | cs |
◦ 부모 Class Type의 참조변수로 자식 Class의 Instance를 참조하는 것이 가능하다.
◦ 자식 Class Type의 참조변수로 부모 Class의 Instance를 참조하는 것은 불가능하다.
◦ 자식 Class의 Instance를 참조할 경우
▹ 같은 Type의 Instance로 생성되었을 지라도 참조변수의 Type에 따라 사용할 수 있는 Member Variable의 개수가 달라진다.
- 참조변수의 형변환
· 기본형 변수처럼 참조변수도 형변환이 가능하며 서로 상속 관계에 있는 Class 사이에서만 가능하다.
· 형변환
◦ 범위상 큰 자식 Class Type의 참조변수가 부모 Class Type의 참조변수로 형변환 시 형변환을 생략 가능하다.
◦ 범위상 작은 부모 Class Type의 참조변수가 자식 Class Type의 참조변수로 형변환 시 형변환을 생략 불가능하다.
◦ 생략 가능 & 생략 불가능 이유
▹ 생략 가능
▸ 자식 Class Type의 참조변수를 부모 Class Type의 참조변수로 형변환 하는 것은 참조변수가 다룰 수 있는 Member의 개수가 실제 Instance가 갖고 있는 Member의 개수보다 적을 것이 분명하기 때문에 생략하는 것에 대해 문제가 발생하지 않는다.
▹ 생략 불가능
▸ 부모 Class Type의 참조변수를 자식 Class Type의 참조변수로 형변환 하는 것은 참조변수가 다룰 수 있는 Member의 개수가 실제 Instance가 갖고 있는 Member의 개수보다 같거나 많을 것이기 때문에 생략하는 것에 대해 문제가 발생할 수 있다.
▸ Member의 개수가 많을 시 Compile 시에는 문제가 발생하지 않지만 실행시 CastException이라는 예외 상황이 발생할 수 있다.
◦ Example
1 2 3 4 5 6 | Perent P = null; Child C1 = new Child(); Child C2 = null; P = C1; C2 = (Child)P; | cs |
· 형변환 시 사용되는 연산자 : Cast 연산자
◦ 형식
1 | ([Data Type])[Variable Name] | cs |
- instanceof 연산자
1 | [Variable 1] instanceof [Type] | cs |
· 참조변수가 참조하고 있는 Instance의 실제 Type을 알아보는데 사용하는 연산자
· 앞의 변수를 Type으로 검사해 형변환이 가능한지 불가능한지 알려준다.
· 주로 조건문에 사용되며 연산 결과로 true, false를 반환한다.
· 연산결과
◦ true
▹ 참조변수가 검사한 Type으로 형변환 가능하다.
◦ false
▹ 참조변수가 검사한 Type으로 형변환 불가능하다.
- 참조변수와 Instance의 연결
· Member 변수가 부모 Class와 자식 Class에 중복으로 정의된 경우
◦ 부모 Class Type의 참조변수를 사용했을 때는 부모 Class에 선언된 Member로 사용된다.
◦ 자식 Class Type의 참조변수를 사용했을 때는 자식 Class에 선언된 Member로 사용된다.
6. 추상 Class(Abstract Class)
- 추상 Class
· 미완성 Class로 Member와 Method의 선언만 허용되고 정의는 하지 않는 Class를 말한다.
· 추상 Class를 이용해 Instance를 생성할 수 없다.
· 추상 Class는 상속을 통해 자식 Class를 통해서만 완성이 된다.
· 일반적으로 Class를 선언해 같은 이름을 가진 Method를 정의하려면 Method의 이름이 약간 달라질 수 있어 Class Type에 따라 비슷한 내용의 Method가 그때 그떄 달라질 수 있으며 추상 Class를 이용해 내용만 다르게 정의한다면 이름과 기능은 같고 정의부만 다르게 정의할 수 있게되어 정의 시 좀 더 효율적으로 정의할 수 있다.
· 선언 방법
1 2 3 | abstract class [Class Name] { …… } | cs |
- 추상 Method
1 2 3 4 | abstract void [Method Name]() { …… } | cs |
· 추상 Class내에 선언되는 미완성 Method를 말한다.
· 추상 Method는 해당 추상 Class의 자식 Class에 의해서만 완성될 수 있다.
· 자식 Class에서 상속받은 Method 중 하나라도 구현하지 않았다면 해당 자식 Class 또한 추상 Class로 선언해야한다.
- 추상 Class 작성
· 추상화
◦ Class간의 공통점을 찾아네 공통의 부모 Class를 만드는 작업
◦ 대상 : 부모 Class
· 구체화
◦ 상속을 통해 Class를 구현하고 확장하는 작업
◦ 대상 : 자식 Class
7. Interface
- Interface
· 추상 Class의 일종으로 추상화 정도가 높아 일반적인 추상 Class와는 달리 Member Variable을 선언하는 것이 불가능하며 Method 또한 선언만 가능하다.
· Member Variable은 선언할 수 없지만 상수는 Member로 선언할 수 있다.
- Interface 작성
1 2 3 4 | interface [Interface Name] { public static final [Type] [Constant Name] = [Value]; public abstract [Method Name]([Variable List]); } | cs |
· 모든 Member Variable은 public static final로 선언해야하며 이를 생략해서 선언해도 상수로 선언된다.
· 모든 Method은 public abstract로 선언해야하며 이를 생략해서 선언해도 추상 Method로 선언된다.
- Interface의 상속
· Interface는 Interface로부터만 상속받을 수 있으며 Class와는 다르게 다중 상속이 가능하다.
· Class와는 달리여러 개의 Interface로부터 상속받는 것이 가능하다.
· Example
1 2 3 4 5 6 7 8 9 10 | interface IF_1 { …… } interface IF_2 { …… } interface IF extends IF_1, IF_2 { …… } | cs |
- Interface의 구현
· Interface는 자체로 Instance를 선언할 수 없으며 Interface를 완성시키기 위해서는 Class에 상속해 통해 완성해야한다.
· 형식
1 2 3 | class [Class Name] implements [Interface Name] { …… } | cs |
- Interface의 장점
· 개발시간 단축
· 표준화 가능
· 서로 관계없는 Class들에게 관계를 맺어줄 수 있음
· 독립적인 Programming 가능
'Java > Theory' 카테고리의 다른 글
Chapter 6. Collection Framework (0) | 2015.08.19 |
---|---|
Chapter 5. Inner Class (0) | 2015.08.19 |
Chapter 4. java.lang Package (0) | 2015.08.19 |
Chapter 3. Exception Handling (0) | 2015.08.19 |
Chapter 1. 객체 지향 프로그래밍 I (0) | 2015.08.19 |