21 다형성(Polymorphism)
다형성
다형성(polymorphism)이란 하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것을 의미한다
쉽게 생각하면 리모컨을 생각해보자 !
리모컨을 사용할때 기능은 버튼을 누르는것이지만 어느 버튼이냐에 따라 기능이 다르다.
1. Overloading(오버로딩)
같은 이름의 메소드를 넘겨서(여러개) 불러오는 기법이다.
매개변수의 개수 혹은 타입이 다르면 같은 이름의 메소드로 여러개 선언할 수 있다.
이름이 아니라매개변수로 구분하기 때문이다.
오버로딩된 메소드 사용시, 전달된 값의 타입 혹은 개수로 구분하여 알맞은 메소드가 자동으로 호출된다.
public class Car {
String brand;
String color;
int price;
public Car(int price) {
this.price = price;
}
// 생성자 오버로딩
Car(String color, int price) {
this.color = color;
this.price = price;
}
// 생성자 오버로딩
Car(String brand, String color, int price) {
this.brand = brand;
this.color = color;
this.price = price;
}
}
이런식으로 같은 이름이지만 필요에따라 원하는 매개변수를 받아 올 수 있다.
하지만, 타입이 같고 갯수가 같은 경우에는 사용 불가능 하다
Car(String color, int price) {
this.color = color;
this.price = price;
}
Car(String brand, int price) {
this.brand = brand;
this.price = price;
}
위 처럼 color와 brand는 이름이 다를 뿐이지 타입이 String으로 같으므로 불가능한 코드이다.
2. Overriding(오버라이딩) : 재정의
부모 필드에 이미 a()라는 메소드가 존재한다면 자식 객체 생성시 부모 생성자가 먼저 호출되기 때문에
부모 클래스의 a()가 먼저 메모리에 올라간다. 그 다음 자식의 필드가 생성될 때 같은 이름의 a()라는
메소드가 선언되어 있다면, 같은 이름으로 두개가 만들어지는게 아니라, 기존에 만들어진 부모 필드의
a() 메소드에 자식에서 작성한 메소드 내용이 덮어 씌워진다. 그러므로 자식 객체로 a()라는 메소드를 사용하게 되면 재정의된 기능으로 사용하며 이것을 재정의(오버라이딩)이라고 한다.
쉽게 예시를 들자면 아래와 같다
부모 클래스 Animal
public class Animal {
String gender;
String name;
int age;
public Animal(String name, String gender, int age) {
this.gender = gender;
this.name = name;
this.age = age;
}
void sleep() {
System.out.println(name + "이(가) 쿨쿨 자는중");
}
void speak() {
System.out.println(name + "이(가) 멍멍");
}
}
자식 클래스 Cat
public class Cat extends Animal {
public Cat(String name, String gender, int age) {
super(name, gender, age);
}
@Override
void speak() {
System.out.println(name + "이(가) 야옹");
}
}
자식 클래스 Pig
public class Pig extends Animal {
public Pig(String name, String gender, int age) {
super(name, gender, age);
}
@Override
void speak() {
System.out.println(name + "이(가) 꿀꿀");
}
}
오버로딩 vs 오버라이딩
오버로딩 | 메소드 이름은 같으나 매개변수가 다른 메소드를 중복으로 선언 |
오버라이딩 | 상속받은 메서드의 내용을 재정의 (메소드 이름, 반환형, 매개변수 이 세가지가 모두 같아야한다.) |
위에서 배운 다형성을 사용하여 이전에 만든 자동차 클래스를 업그레이드 해보자(ง •̀_•́)ง
부모클래스 : Car
public class Car {
String brand;
String color;
int price;
static int wheel = 4;
Car(){ }
//Alt + Shift + S > O : 필드를 이용해서 생성자 만들기
Car(String brand, String color, int price) {
this.brand = brand;
this.color = color;
this.price = price;
}
void engineStart() {
System.out.println(brand + " 시동 켜기");
}
void enginStop() {
System.out.println(brand + " 시동 끄기");
}
}
자식 클래스 : SuperCar
public class SuperCar extends Car {
String pw;
public SuperCar() {}
public SuperCar(String brand, String color, int price) {
super(brand, color, price);
}
public SuperCar(String brand, String color, int price, String pw) {
super(brand, color, price);
this.pw = pw;
}
@Override
void engineStart() {
System.out.println(brand + " 음성으로 시동 켜기");
}
@Override
void engineStop() {
System.out.println(brand + " 음성으로 시동 끄기");
}
void roofOpen() {
System.out.println(brand + " 뚜껑 열기");
}
void roofClose() {
System.out.println(brand + " 뚜껑 닫기");
}
}
부모클래스에서의 시동을 켜고 끄는 메소드를 오버라이딩을 통해 재정의를 하였다
부모클래스 : 열쇠로 시동 On/Off
자식클래스 : 음성으로 시동 On/Off
메인 클래스 : Road
public class Road {
public static void main(String[] args) {
SuperCar mycar = new SuperCar("Ferrari", "Red", 65000, "abcd");
mycar.engineStart();
mycar.roofOpen();
Car momcar = new Car("K7", "White", 7000);
momcar.engineStart();
Car dadcar = new Car();
}
}
Ferrari 음성으로 시동 켜기
Ferrari 뚜껑 열기
K7 시동 켜기