class Parent{
int data;
void f() {
System.out.println("부모의 메소드");
}
}
class Child extends Parent{
double data2;
@Override
void f() {
System.out.println("자식의 메소드");
}
B b = new B();
b 객체는 실제로는 A의 필드와 B의 필드 둘 다 가지고 있다.
A : 부모 클래스, 상위 클래스, 슈퍼 클래스, 기반 클래스
B : 자식 클래스, 하위 클래스, 서브 클래스, 파생 클래스
자식 클래스의 객체는 자식 생성자를 호출하여 객체화를 진행한다.
자식 생성자를 호출했으므로 자식 클래스의 필드가 메모리에 올라갈 것이다.
메모리에 자식 클래스의 필드만 올라갔다면 자식 객체로 절대
부모 클래스에 있는 필드에 접근할 수 없다. 따라서 자식 생성자를
호출하게 되면 자식 클래스가 상속받기로 약속되어 있는 부모 클래스의
생성자가 자동으로 먼저 호출이 된다. 그 이후에 자식 클래스의 필드가
부모 클래스의 필드에 이어붙어서 객체의 필드가 완성되게 된다.
따라서 자식 클래스로 만든 객체는 부모 필드가 먼저 메모리에 생성되어
있기 때문에 접근이 가능해진다.
자식 생성자의 첫 줄에는 항상!!! super클래스의 생성자가 호출된다.
명시적으로 적지 않을시에는 보이진 않지만 super() 호출 = 부모의 기본 생성자를 호출
static이 붙은 변수, 메소드, 구역 등은 프로그램 실행시 가장 먼저
메모리에 올라간다. static이 붙은 메소드는 내부에서 객체의 필드에
올라오는 일반 전역변수와 일반 메소드는 아직 존재하지 않기 때문에
프로그램 실행시 해석이 불가하여 사용할 수 없다.
따라서 static이 붙은 전역변수, static이 붙은 메소드, 자기 자신
안에 선언된 지역변수만 사용할 수 있다.
static이 붙은 전역변수, 메소드는 모든 객체가 공유한다.
따라서 static필드는 클래스 이름으로 직접 접근이 가능하다.
실제로 객체들이 공유해야 하는 값, 메소드, 필드를 사용하지 않는 메소드에는
static을 붙여서 선언한다.(공유하지 않아야 하는 필드는 무조건 static을 붙이면 안된다.)
부모 타입의 객체에 자식 클래스의 필드를 담아주는 것
부모 타입의 객체에 자식 객체를 넣어주는 것
부모 타입의 객체에 자식 생성자를 호출해주는 것
업 캐스팅 된 객체는 자식 클래스에서 추가된 내용을 사용할 수 없다.
단, 오버라이딩 된 메소드는 가지게 된다.
부모 클래스 객체명 = new 자식생성자();
부모 클래스 객체명 = 자식객체;
Parent up = new Child();
업 캐스팅 된 객체를 다시 자식 객체에 담는 기법
업 캐스팅 된 객체에 다시 자식 클래스의 필드를 달아주는 것
업 캐스팅시 잘려나갔던 자식 클래스의 내용들을 다시 사용할 수
있게 하려면 자식 클래스 타입으로 바꿔주어야 한다.
(자식클래스)업 캐스팅 된 객체
자식클래스 다운 캐스팅 객체 = (자식클래스)업 캐스팅 된 객체
다운 캐스팅 객체.필드
Child down = (Child)up;
객체 instanceof 클래스명
객체가 뒤에오는 클래스 타입이면 true 아니면 false
부모객체 instanceof 부모클래스 : true
자식객체 instanceof 자식클래스 : true
부모객체 instanceof 자식클래스 : false
자식객체 instanceof 부모클래스 : true
업캐스팅객체 instanceof 부모클래스 : true
업캐스팅객체 instanceof 자식클래스 : true