✏️ Info.
- Java 상속 학습
📋 List.
1. 자바 상속의 특징
2. super 키워드
3. 메서드 오버 라이딩
4. 다이내믹 메서드 디스패치 (Dynamic Method Dispatch)
5. 추상 클래스
6. final 키워드
7. Object 클래스
✔️ Content.
1. 자바 상속의 특징
* 상속 : 자식이 부모로부터 무언가 물려받는 것
- Java 상속 : 자식 클래스가 기존의 부모 클래스로부터 기능을 물려받아 자식의 클래스에 기능을 추가하거나, 나 재정의하여 새로운 클래스를 정의하는 것.
장점
- 클래스, 멤버 재활용
- 클래스 간의 계층 관계 구성으로 다형성 토대 마련
특징
- 하나의 클래스만 상속 - 다중 상속 불가능
- 부모 클래스의 멤버와 메서드만이 상속되며, 생성자와 초기화 블록은 상속되지 않는다.
- 부모 클래스의 접근제어가 private 또는 default로 설정된 멤버는 자식 클래스가 상속받지만 접근할 수 없다.
- 기본적으로 클래스는 Object 클래스를 상속받는다.
사용
- 사용하고자 하는 클래스 뒤에 'extends'와 함께 상속받고자 하는 클래스를 작성해 주면 된다.
// 부모 클래스
class parentClass{}
// 자식 클래스
class childClass extends parentClass{}
부모 클래스 : parentClass
자식 클래스 : childClass
* 실습 과정에서 캐스팅에서 오류를 발견했다.
public static void main(String[] args) {
parentClass parentClass = new parentClass();
parentClass childClass = new childClass();
childClass childClass1 = new childClass();
childClass childClass2 = (childClass) new parentClass(); //부모 객체에 자식 인스턴스 생성 가능 하지만, 자식 객체에 부모 인스턴스는 불가능
}
위의 3개의 인스턴스 생성에서는 문제가 없지만
자식 클래스 객체에 부모 인스턴스 생성은 불가능했다.
- 인스턴스 생성에는 클래스가 필요로 하는 정보를 채워줘야 한다.
- childClass chidClass2는 childClass 클래스가 필요로 하는 정보를 채워줘야 하는데 parentClass 클래스는 childClass 클래스 필요 정보를 가지고 있지 않기 때문에 채워 넣을 수 없다.
- 또한 위의 코드에서 (childClass)로 캐스팅할 경우 Compile Error는 나지 않지만 RunTime Error가 발생한다.
- Compile은 캐스팅을 했기 때문에 데이터 주입이 가능하다 판단하고 Error를 발생하지 않는다
- RunTime은 JVM이 런타임 과정에서 실제로 데이터 주입하면서 필요로 하는 데이터를 찾지 못하기 때문에 Casting Error를 발생시킨다.
2. super 키워드
* 상속받은 부모 클래스의 멤버, 메서드를 불러올 때 사용
사용
- super.said() : parentClass의 said() 함수 호출
- super.name : parentClass의 name 멤버 호출
class parentClass{
String name = "Mom";
void said(){
System.out.println("HI, " + this.getClass().getSimpleName());
}
}
class childClass extends parentClass{
private void child(){
super.said();
System.out.println(super.name);
}
}
3. 메서드 오버 라이딩
* 상속받은 부모 클래스의 메서드를 재정의 할 때 사용
사용
- childClass의 said() : parentClass의 said() 함수를 재정의해서 사용
class parentClass{
void said(){
System.out.println("HI, " + this.getClass().getSimpleName());
}
}
class childClass extends parentClass{
@Override
void said() {
System.out.println("NO, HI");
}
}
4. 다이내믹 메서드 디스패치 (Dynamic Method Dispatch)
* Method Dispatch : 어떤 메서드를 호출할지 결정하여 실제로 실행시키는 과정
1. Static Dispatch
- Compile 시점에서 이미 컴파일러가 특정 메소드를 호출할 것을 명확하게 알고 있는 경우
- Compile 시 생성된 Byte Code에도 이 정보가 그대로 남아있다.
- ex) 객체의 변수 타입과 인스턴스의 타입이 같을 경우
public static void main(String[] args) {
parentClass parentClass = new parentClass();
childClass childClass1 = new childClass();
}
2. Dynamic Dispatch
- Interface(인터페이스) or Abstract Class(추상화 클래스)에서 정의된 abstract method를 호출하는 경우에 해당
- 아래의 예를 보면 main에서는 childClass가 new childClass();에 의해 인스턴스가 생성됨을 알 수 있지만, 실제로 Dispatcher 내부에서는 파라미터로 받은 childClass의 객체에 바인딩된 클래스는 compile단계에서 알 수 없으며 Runtime 단계에서 결정되므로 Dynamic Dispatch에 해당한다.
- ex)
public static void main(String[] args) {
parentClass childClass = new childClass();
new Dispatcher().doAction(childClass)
}
class Dispatcher{
public void doAction(parentClass childClass){
childClass.doAction();
}
}
! 추가 공부 사항 - Double Dispatch
5. 추상 클래스
* 객체 지향 프로그래밍에서 중요한 특징인 다형성을 가지는 메서드의 집합을 정의
- 즉, 반드시 사용되어야 하는 메서드를 추상 클래스에 추상 메소드로 선언해 놓으면, 이 클래스를 상속받는 모든 클래스에서는 이 추상 메소드를 반드시 재정의 해야 한다.
- 하나 이상의 추상 메소드를 포함하는 클래스
- 추상 메소드를 포함하는 것을 제외하면 일반 클래스와 모든 점이 같다.
- 추상 클래스는 인스턴스를 생성할 수 없다
사용
abstract class ClassName{
abstract void methodName();
}
6. final 키워드
* 마지막, 변경될 수 없는 의미를 가진다.
- final 클래스 : 변경될 수 없는 클래스, 확장될 수 없는 클래스
- final 메소드 : 변경될 수 없는 메서드, overriding 불가
- final 변수 : 값을 변경할 수 없는 상수가 된다.
public final class Fclass{
final int fVal = 0;
public final void fMethod(){
System.out.println("fMethod");
}
}
7. Object 클래스
* 모든 클래스의 부모가 되는 클래스, extends 가 없는 클래스에 컴파일러는 자동으로 Object클래스를 상속한다.
메서드 | 설명 |
protected Object clone() | 해당 객체를 복제하여 새로운 인스턴스를 생성해 반환한다. 필드의 값만을 복사하므로, 필드 값이 배열, 인스턴스면 제대로 복제될 수 없다. 필요시 재정의해서 구현 |
public boolean equals(Object obj) | 객체 자신과 입력받은 객체 obj가 같은 객체인지 반환 |
protected void finalize() | 객체가 소멸될 때 가비지 컬렉터에 의해 자동적으로 호출한다. |
public Class getClass() | 객체 자신의 클래스 정보를 담고 있는 인스턴스를 반환한다. |
public int hashCode() | 객체 자신의 해시코드를 반환한다. |
public String toString() | 객체 자신의 정보를 문자열로 반환한다. 이때 반환 되는 문자열은 클래스 이름과 함께 구분자로 '@'가 사용되며, 그뒤로 16진수 해쉬코드(hash code)(인스턴스 주소 값)가 추가 된다. |
public void notify() | 객체 자신을 사용하려고 기다리고 있는 쓰레드 하나만 깨워준다. |
public void notifyAll() | 객체 자신을 사용하려고 기다리고 있는 쓰레드를 모두 깨워준다. |
public void wait() public void wait(long timeout) public void wait(long timeout, int nanos) |
다른 쓰레드가 notify() 또는 notifyAll()을 호출할 떄까지 현재 쓰레드를 무한히 또는 지정된 시간 동안 기다리게 한다. |
❗️ Refer.
- 상속
https://wikidocs.net/280
http://www.tcpschool.com/java/java_inheritance_concept
(다운 캐스팅) https://mommoo.tistory.com/51
- 다이내믹 메서드 디스패치 (Dynamic Method Dispatch)
https://defacto-standard.tistory.com/413
-Object
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
http://www.tcpschool.com/java/java_api_object
'Live-Study' 카테고리의 다른 글
[8주차] 인터페이스 (0) | 2021.02.19 |
---|---|
[7주차] 패키지 (0) | 2021.02.19 |
[5주차] 클래스 (0) | 2021.01.04 |
[4주차] 제어문 (0) | 2020.12.31 |
[3주차] 연산자 (0) | 2020.11.23 |