자식 객체가 부모 객체의 옷을 입고 부모행세. 그러나 자식 객체가 가지고 있는 데이터를 출력한다.
자식 -> 부모 : 자동 타입변환 // 부모->자식: 강제 타입변환
오버라이딩을 통해 다형성 구현
해당 클래스의 객체 대입이 원칙이나 자식 객체 대입하는 것도 허용
Driver, DriverEx, Taxi, Bus, Vehicle
public class Vehicle {
public void run(){
System.out.println("차량이 달립니다.");
}
}
public class Bus extends Vehicle{
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
}
public class Taxi extends Vehicle{
@Override
public void run(){
System.out.println("택시가 달립니다.");
}
}
public class Driver {
public void drive(Vehicle vehicle){
vehicle.run();
}
}
import package1.B;
import package2.D;
public class DriverEx {
public static void main(String[] args) {
Driver driver = new Driver();
Bus bus = new Bus();
Taxi taxi =new Taxi();
driver.drive(new Vehicle());
driver.drive(bus);
driver.drive(taxi);
}
}
부모 타입을 자식 타입으로 변환하는 것.
조건: 자식 타입을 부모 타입으로 자동 변환 후, 다시 자식 타입으로 변환할 때
자식 타입에 선언된 필드와 메서드를 다시 사용해야 할 경우 필요하다.
instace of사용하여 변환 가능한지 확인을 먼저 해야 한다. 안하면 오류남.
원래 자신이었던 것만 가능.
좌항(부모타입) 우항(원본타입)
boolean해서 true나와야 변환이 가능하다.
parent2 child2 child2ex
public class Parent2 {
public String field1;
public void method1(){
System.out.println("부모 메서드1 실행");
}
public void method2(){
System.out.println("부모 메서드2 실행");
}
}
public class Child2 extends Parent2{
public String field2;
public void method3(){
System.out.println("자식 메서드3 실행");
}
}
import package2.C;
public class Child2Ex {
public static void main(String[] args) {
// 자동 타입 변환
// 부모 클래스 타입의 변수에 자식 클래스 타입의 객체를 대입하면 부모 클래스 타입의 멤버만 사용이 가능하다.
// (알맹이는 자식 클래스 타입의 객체)
Parent2 parent2 = new Child2();
parent2.field1 = "data1";
parent2.method1();
parent2.method2();
// parent2.field2 = "데이터2"; //error 부모 흉내를 내고 있기 때문에 본인이 가지고 있는 것을 사용하지못한다.
// parent2.method3(); //error
System.out.println("\n=====자식 클래스 타입의 변수에 자식 클래스 타입의 객체 대입=====\n"); // 상속받은 모든 걸 사용할 수 있다.
Child2 child2 = new Child2();
child2.field1 = "데이터1";
child2.field2 = "데이터2";
child2.method1();
child2.method2();
child2.method3();
System.out.println("\n------다시 자식 클래스 타입으로 돌아갈 때------\n");
Child2 child21 = new Child2();
child21.field1 = "Parent2에서 상속받은 멤버 변수"; //상속
child21.field2 = "전용으로 가지고 있는 멤버 변수";
System.out.println("객체 child21의 field1 출력 : " + child21.field1);
System.out.println("객체 child21의 field2 출력 : " + child21.field2);
System.out.println("객체 child21의 method1 실행 : ");
child21.method1(); //상속
System.out.println("객체 child21의 method2 실행 : ");
child21.method2(); //상속
System.out.println("객체 child21의 method3 실행 : ");
child21.method3();
System.out.println("\n부모 객체로 자동 타입 변환 \n");
Parent2 parent21 = child21;
System.out.println("객체 parent21의 field1 출력" + parent21.field1);
// System.out.println("객체 parent21의 field1 출력" + parent21.field2); //에러난다.
System.out.println("객체 parent21의 field1 출력 : " + parent21.field1);
// System.out.println("객체 parent21의 field2 출력 : " + parent21.field2); // 에러 난다. 자식 클래스 전용
System.out.println("객체 parent21의 method1 실행 : ");
parent21.method1(); //상속
System.out.println("객체 parent21의 method2 실행 : ");
parent21.method2(); //상속
System.out.println("객체 parent21의 method3 실행 : "); //자식 클래스 타입의 전용이기 때문에 사용안된다.
// parent21.method3(); 에러
System.out.println("\n다시 자식 클래스 타입으로 변환\n");
// 자식 클래스 타입의 변수에 부모 클래스 타입의 객체를 대입하면 오류 발생
// 원본 객체를 자식 클래스 타입의 변수로 타입 변환 시 해당 객체의 모든 멤버를 가지고 있는지
// 알 수 없기 때문에 강제 타입 변환을 해야 한다.
Child2 child22 = (Child2)parent21; //무조건 앞에 () 씌워야
// child22.field1 = "Parent2에서 상속받은 멤버 변수"; //상속
// child22.field2 = "전용으로 가지고 있는 멤버 변수";
System.out.println("객체 child22의 field1 출력 : " + child22.field1);
System.out.println("객체 child22의 field2 출력 : " + child22.field2);
System.out.println("객체 child22의 method1 실행 : ");
child22.method1();
System.out.println("객체 child22의 method2 실행 : ");
child22.method2();
System.out.println("객체 child22의 method3 실행 : ");
child22.method3();
System.out.println("\n다시 자식 클래스 타입으로 변환되는 조건\n");
// 1. 원본이 자식 클래스 타입이어야 해당하는 자식 클래스 타입으로 변환이 가능.
// 원본이 부모 클래스 타입
// Parent2 parent23 = new Parent2();
//// 자식 클래스 타입의 변수 선언
// Child2 child23;
//// 자식 클래스 타입의 변수에 부모 클래스 타입의 객체를 대입
//// 문법 상의 오류는 없으나 원본이 자식 클래스 타입의 객체가 아니기 때문에 런타임 에러(실행하는 순간 에러)가 발생
// child23 = (Child2) parent23; //여기서 오류 child23 = (Child2) parent23;
//// 자식 클래스 타입의 객체의 멤버를 사용
// child23.method3();
Parent2 parent24 = new Child2(); //알맹이는 child2
castMethod1(parent24); //성공
castMethod2(parent24); //성공
Parent2 parent25 = new Parent2();
castMethod1(parent25); //25로 변환되지 않음
castMethod2(parent25); //오류 발생
}
public static void castMethod1(Parent2 parent){
// instanceof 연산자를 사용하면 현재의 객체가 지정한 타입의 객체인지 확인이 가능함. 반드시 사용하자.
if(parent instanceof Child2){
Child2 child = (Child2) parent;
System.out.println("castMethod1 - Child2로 변환 성공");
}
else{
System.out.println("castMethod2 - Child2로 변환 되지 않음");
}
}
public static void castMethod2(Parent2 parent){
// 원본 객체가 변환하려는 클래스 타입의 객체가 아닐 수 있기 때문에 오류가 발생할 수 있음.
Child2 child = (Child2) parent;
System.out.println("castMethod1 - Child2로 변환 성공");
}
}
추상메서드
다. 일반 멤버와 일반 멤버 메서드는 하나도 없다. 전부 다 추상메서드로 이루어져 있다.[public] interface 인터페이스명{...}
default 혹은 public을 주로 사용한다. 그냥 public붙여라..
{ ... }에 추상메서드 넣어라.
public abstract 생략하더라도 자동적으로 컴파일에 생긴다. 생략해도 된다.
=> 자식 클래스에게 상속을 받아 사용해야한다.
마지막 사용 단어를 제외하고는 거의 동일하다.
인터페이스 변수명 = new 자식객체(){...}
public class SmartTelevision implements RemoteControl,Searchable{
private int volume;
@Override
public void turnOn() {
System.out.println("스마트tv를 켭니다");
}
@Override
public void turnOff() {
System.out.println("스마트tv를 끕니다");
}
@Override
public void setVolume(int volume) {
if(volume > RemoteControl.MAX_VOLUME){
this.volume = RemoteControl.MAX_VOLUME;
} else if (volume < RemoteControl.MIN_VOLUME) {
this.volume = RemoteControl.MIN_VOLUME;
}
else{
this.volume = volume;
}
System.out.println("현재 스마트tv볼륨 : " + this.volume);
}
@Override
public void search(String url) {
System.out.println(url + "을 검색합니다");
}
}
RemoteControl.changeBattery();
setMute()
Car5 HankookTire2 KumhoTire2 Car4ex
Vehicle2 bus2 taxi2 driver2 Driver2EX
driverex2
public static void main(String[] args) {
System.out.println("각각 객체를 생성해서 실행");
Bus2 bus2 = new Bus2();
Taxi2 taxi2 = new Taxi2();
bus2.run();
taxi2.run();
System.out.println("\n익명 객체를 통한 구현");
// Vehicle2 vehicle2 = new Vehicle2(); 이거안됨
Vehicle2 vehicle2 = new Vehicle2() {
@Override
public void run() {
System.out.println("탈 것이 달립니다");
}
};
vehicle2.run();
System.out.println("\n부모 인터페이스 타입의 변수에 자식 객체를 대입");
vehicle2 = bus2;
vehicle2.run();
vehicle2=taxi2;
vehicle2.run();
System.out.println("\n 인터페이스 변수를 매개변수로 사용시 ");
Driver2 driver2 = new Driver2();
driver2.drive(bus2);
driver2.drive(taxi2);
///강제 타입변환 예제
System.out.println("\n-----자동 타입변환, 강제 타입변환, instanceof------\n");
// 자동 타입 변환, 부모인 Vehicle2 인터페이스 타입의 변수에 자식인 Bus2 클래스 타입의 객체를 대입
Vehicle2 vehicle21 = new Bus2();
vehicle21.run();
// 데이터 타입이 다르므로 강제 타입 변환을 시도해야 함.
// Bus2 bus21 = vehicle21;
// 강제 타입 변환의 조건이 원본이 자식 클래스 타입의 객체일 때 해당 클래스 타입으로 변환 시 가능
// 원본 클래스 객체 타입이 맞는지 확인을 하기 위해서는 instanceof 연산자를 사용해야 함
Bus2 bus21 = (Bus2) vehicle21;
bus21.run();
Vehicle2 vehicle22 = new Bus2();
vehicle22.run();
// Taxi2 taxi22 = (Taxi2) vehicle22; //오류발생. instanceof로 확인해야.
// taxi22.run();
if(vehicle22 instanceof Taxi2){ //변경할 수 없다고 뜬다.
Taxi2 taxi22 = (Taxi2) vehicle22;
taxi22.run();
System.out.println("정상적으로 Taxi2 클래스 타입으로 변경 했습니다.");
}
else {
System.out.println("Taxi2 클래스 타입으로 변경할 수 없습니다.");
}
}
}
RemoteControl, Audio, Television, Searchable, SmartTelevition, RemoteControlEx
InterfaceA ImplC InterfaceB InterfaceC
InterfaceA
public interface InterfaceA {
public void methodA();
}
InterfaceB
public interface InterfaceB {
public void methodB();
}
InterfaceC
public interface InterfaceC extends InterfaceA,InterfaceB{
public void methodC();
}
ImplC
public class ImplC implements InterfaceC{
@Override
public void methodA() {
System.out.println("구현클래스 C / ImplementC - 메서드A 실행");
}
@Override
public void methodB() {
System.out.println("구현클래스 C / ImplementC - 메서드B 실행");
}
@Override
public void methodC() {
System.out.println("구현클래스 C / ImplementC - 메서드C 실행");
}
}
ImplEx
public class ImplEx {
public static void main(String[] args) {
System.out.println("구현체 implC의 객체 impl은 모든 메서드 사용 가능");
ImplC impl = new ImplC();
impl.methodA();
impl.methodB();
impl.methodC();
System.out.println("\nInterfaceA의 변수에 대입 시");
InterfaceA ifA = impl;
ifA.methodA();
System.out.println("\nInterfaceB의 변수에 대입 시");
InterfaceB ifB = impl;
ifB.methodB(); //b만 있음
System.out.println("\nInterfaceC의 변수에 대입 시");
InterfaceC ifC = impl;
ifC.methodC(); //3개가 다 있다. 할머니, 할아버지께 다 물려받음
ifC.methodB();
ifC.methodA();
}
}