다형성은 객체지향 프로그래밍의 3대 특징 중 하나로, 하나의 행동이 여러 형태를 가질 수 있는 것을 의미합니다. 이는 상속을 통해 구현되며, 부모 타입으로부터 파생된 여러 가지 타입의 자식 객체를 부모 클래스 타입 하나로 다룰 수 있는 기술입니다. 다형성은 코드를 더욱 유연하고 재사용 가능하게 만들어줍니다.
업캐스팅은 자식 타입의 객체를 부모 타입의 참조변수로 가리키는 것을 말합니다. 이는 자동으로 처리됩니다.
package i.polymorphism.ex1; public class Cake { public void sweet() { System.out.println("cake sweet"); } public void yummy() { System.out.println("cake yummy"); } }
package i.polymorphism; public class CheeseCake extends Cake { public void milky() { System.out.println("cake milky"); } @Override public void yummy() { System.out.println("CheeseCake yummy"); } }
package i.polymorphism; public class Run { public static void main(String[] args) { Cake c1 = new CheeseCake(); c1.sweet(); c1.yummy(); } }
코드를 보면 Cake 타입의 참조변수 c1은 CheeseCake 객체를 가리키고 있습니다. c1을 통해 sweet 메소드를 호출하면 부모 클래스의 메소드가 실행되지만, yummy 메소드는 오버라이딩된 자식 클래스의 메소드가 호출됩니다.
다운캐스팅은 부모 타입의 참조변수를 자식 타입으로 변환하는 것입니다. 이는 명시적으로 형 변환을 해주어야 합니다.
package i.polymorphism.ex2; public class Car { private String color; private String fuel; private int year; public Car() { super(); } public Car(String color, String fuel, int year) { super(); this.color = color; this.fuel = fuel; this.year = year; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getFuel() { return fuel; } public void setFuel(String fuel) { this.fuel = fuel; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } @Override public String toString() { return year + "연식 " + " " + fuel + " " + "색깔 : " + color; } public void drive() { System.out.println("부릉부릉~"); } }
package i.polymorphism.ex2; public class Avante extends Car { public Avante(String color, String fuel, int year) { super(color, fuel, year); } @Override public void drive() { System.out.println("슝~슝~"); } public void moveAvante() { System.out.println("아반떼 이동"); } }
package i.polymorphism.ex2; public class Sonata extends Car { public Sonata(String color, String fuel, int year) { super(color, fuel, year); } @Override public void drive() { System.out.println("부릉~ 부릉~"); } public void moveSonata() { System.out.println("소나타 이동"); } }
package i.polymorphism.ex2; public class Run { public static void main(String[] args) { Car c1 = new Car("빨간색", "가솔린", 2020); c1.drive(); System.out.println("=================="); Avante c2 = new Avante("검은색", "디젤", 2022); c2.drive(); c2.moveAvante(); System.out.println("=================="); Car c3 = c2; c3.drive(); System.out.println("=================="); Car c4 = new Sonata("흰색", "가스", 2023); c4.drive(); ((Sonata) c4).moveSonata(); } }
instanceof 연산자를 사용하여 현재 참조형 변수가 어떤 클래스 형의 객체를 참조하고 있는지 확인할 수 있습니다.
package i.polymorphism.ex2; public class Run { public static void main(String[] args) { Car[] carArr = new Car[10]; carArr[0] = new Sonata("흰색", "가스", 2022); carArr[1] = new Avante("검은색", "디젤", 2023); if (carArr[i] instanceof Sonata) { ((Sonata) carArr[i]).moveSonata(); } else if (carArr[i] instanceof Avante) { ((Avante) carArr[i]).moveAvante(); for (int i = 0; i < carArr.length; i++) { } else { carArr[i].drive(); } } } }