부모클래스 변수명 = new 자식클래스();

//Sonata 클래스는 Car 클래스의 후손
Car c = new Sonata();
//Sonata클래스형에서 Car클래스형으로 바뀜
* 부모로부터 상속 받은 멤버만 참조 가능
//Sonata 클래스는 Car 클래스의 후손
Car c = new Sonata();
((Sonata)c).moveSonata();
System.out.println(((Tesla)c1).getBatteryCapacity());
// 주의!
// "." 연산자 (Tesla) 형변환하는 연산자보다 우선순위 높음
// 그래서 형변환 하는 부분을 ()로 묶어주고 . 연산을 진행해야
// Tesla 객체의 getBatteryCapacity()를 사용할 수 있음
** 클래스 간의 형 변환은 반드시 상속 관계인 클래스 끼리만 가능 **
** 업 캐스팅 상태였을 때!! **
Car[] carArr = new Car[5];
carArr[0] = new Sonata();
carArr[1] = new Avante();
carArr[2] = new Grandure();
carArr[3] = new Spark();
carArr[4] = new Morning();
public void execute() {
driveCar(new Sonata());
driveCar(new Avante());
driveCar(new Grandure());
}
public void driveCar(Car c) {}
Car c1 = new Car("경유엔진", "경유", 8); // 평범한 객체
System.out.println(c1.toString());
// edu.kh.poly.ex1.model.dto.Car.toString()
// Car 객체에 있는 toString() 메서드를 호출
// 프로그램 "실행 전"
// 컴파일러는 toString() 메서드가 Car에 있는 걸로 인식해서
// c1.toString() 호출코드와
// edu.kh.poly.ex1.model.dto.Car.toString() 메소드 코드를 연결
// => 정적 바인딩!
Car c2 = new Spark("경차엔진", "휘발유", 4, 0.5); // 업캐스팅
// 업캐스팅 적용 -> 부모 부분만 참조 가능한 상태
System.out.println(c2.toString());
// edu.kh.poly.ex1.model.dto.Car.toString()
// 참조변수 c2가 Car타입이므로
// toString() 호출코드와 Car의 toString() 메소드 코드를 연결
// => 정적 바인딩
// 실행 해보면 자식(Spark)의 toString()이 호출되는 것을 확인
// 경차엔진 / 휘발유 / 4 / 0.5
// -> 컴파일 시에는 부모(Car)와 바인딩 == 정적바인딩
// -> "실행 시"에는 정적바인딩보다 자식(Spark)에서 오버라이딩 된
// toString() 메서드가 우선시 되어 Spark의 메서드와 바인딩
// => 동적바인딩

if(레퍼런스 instanceof 클래스타입) {
//true일때 처리할 내용, 해당 클래스 타입으로 down casting
}
if(c instanceof Sonata) {
((Sonata)c).moveSonata();
} else if (c instanceof Avante){
((Avante)c).moveAvante();
} else if (c instanceof Grandure){
((Grandure)c).moveGrandure();
}
Car c1 = new Tesla();
// Tesla 객체를 만들어 Car타입 참조변수 c1에 담음
// Spark s1 = (Spark)c1;
// 다운캐스팅 잘못해도 컴파일 에러 발생 안함
// -> 실행 시 발생 (런타임 에러)
// ClassCastException : 형변환 에러
// 해결방법 : instanceof 연산자와 같이 사용하면 된다
// 예외 처리
if(c1 instanceof Spark) { // c1이 Spark이거나 상속관계인가?
// 맞다면
Spark s1 = (Spark)c1; // 다운캐스팅
System.out.println("성공");
} else { // 아니라면
System.out.println("실패, Spark타입/상속관계 아님");
}
[접근제한자] abstract class 클래스명 {}
여러 타입들을 관리하기 위한 상위 타입의 목적,
객체로 생성하여 사용하기 위한 목적이 아님!
[접근제한자] abstract 반환형 메소드명(자료형 변수명);
public abstract void ex2();
[접근제한자] interface 인터페이스명 {
//상수도 멤버로 포함할 수 있음
public static final 자료형 변수명 = 초기값;
//추상 메소드만 선언 가능
[public abstract] 반환자료형 메소드명([자료형 매개변수]);
//public abstract가 생략되기 때문에
//오버라이딩 시 반드시 public 표기해야 함
}
- 인터페이스 == 미완성 설계도 == 객체 생성 불가능 => 참조변수로는 사용 가능
- 코드의 큰 수정 없이 객체 생성 코드만 바꾸면 새로운 클래스 코드를 수행할 수 있다.
- 인터페이스를 부모 참조변수로 사용하면 다형성 중 업캐스팅이 적용돼서,
상속받은 모든 클래스를 자식객체로 참조할 수 있다.
-> 이를 이용하여 중요한 메인코드의 수정을 최소화 할 수 있다!- 자식클래스에 공통된 메서드를 강제 구현하라고 하기 때문에,
모든 자식클래스가 동일한 형태를 띄게 된다.
-> 이를 이용하여 공동작업(팀 프로젝트)에 필요한 개발환경 조성이 용이하다.

extends : 확장하다 implements : 구현하다
(부)클래스 - (자)클래스 : extends 사용
(부)인터페이스 - (자)인터페이스 : extends 사용
(부)인터페이스 - (자)클래스 : implements 사용
(부)클래스 - (자)인터페이스 : 상속불가!!
