1. 다형적 참조 / 메서드 오버라이딩을 통해 각자 다른 타입을 모두 동일화하여 중복을 제거할 수 있다.
2. 추상 클래스 : 상속을 목적으로 사용되고, 부모 클래스 역할을 담당, 인스턴스 존재X
3. 추상 메서드 : 반드시 오버라이딩 해야하는 메서드
4. 인터페이스 : 순수 추상클래스와 동일하며, 적절한 제약과 다중구현이 가능하다.
5. 인터페이스와 클래스가 같이사용될때, extends 후 implements를 사용해라
6. 추가적으로 객체를 생성하고 배열에 바로 담는 것은 가능
*다형성을 사용하는 이유
- 다향적 참조 / 메서드 오버라이딩을 통해 각자 다른 타입(클래스)를 모두 같은 타입화하여 중복을 제거할 수 있다.
1) 부모 클래스를 생성 방지 대비 - 추상 클래스 사용
2) 부모 클래스를 상속받는 곳에서 특정 기능을 오버라이딩을 누락할 문제 대비 - 추상 매서드 사용
[p.5 / AinmalPolyMain] 다형성 사용을 위한 상속 관계 코드 사용, 부모는 자식을 담을 수 있다.
public class AnimalSoundMain {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(caw);
}
//동물이 추가되어도 변하지 않는 코드
public static void soundAnimal(Animal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
- 매서드 부분을 보면 매개변수에 Animal 타입의 변수만 들어갈 수 있음을 확인할 수 있다.
- 매개변수에 dog가 들어간다는 것은 Animal animal = new Dog();와 같은 의미이다.
- 즉 매서드 오버로딩을 통해 dog의 오버로딩에 접근하고, animal은 자식의 인스턴스를 참조할 수 있다.
ⓛ 다형성 + 메서드 이용
[p. 8 / AnimalPolyMain2] 배열 + for문 ⇒ 상위 부모 변수에 자식 변수를 담은 후 반복 작업한다.
public class AnimalPolyMain2 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
Animal[] animalArr = {dog, cat, caw}; //상위 상속 변수에 변수를 담을 수 있다.
for (Animal animal : animalArr) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
}
② 다형성 + 메서드 + 배열 이용
[p. 8 / AnimalPolyMain2] 배열 + for문 ⇒ 상위 부모 변수에 자식 변수를 담은 후 반복 작업한다.
public class AnimalPolyMain3 {
public static void main(String[] args) {
Animal[] animalArr = {new Dog(), new Cat(), new Caw()};
for (Animal animal : animalArr) {
animalSound(animal);
}
}
public static void animalSound(Animal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
[p. 8 / AnimalPolyMain3] 배열 + for문 + 메서드 ⇒ 배열에 객채 생성을 담은 후 반복 작업한다.
public class AnimalPolyMain3 {
public static void main(String[] args) {
Animal[] animalArr = {new Dog(), new Cat(), new Caw()};
for (Animal animal : animalArr) {
animalSound(animal);
}
}
public static void animalSound(Animal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
- Animal이라는 추상적인 부모를 참조한다.
- 변하는 부분을 최소화하는 것이 잘 작성한 코드이다.
객체를 생성하고 배열에 바로 담는 것은 가능하다.
Animal[] animalArr = {new Dog(), new Cat(), new Caw()};
- 각각 Dog, Cat, Caw 클래스의 객체를 생성하고, 이를 배열에 담고 있다.
- 이는 객체를 생성하고 그 결과를 배열에 저장하는 것을 한 번에 수행는 방법이다.
- 만약 이후에 이 객체들을 변경할 필요가 없고, 한 번 사용하고 마는 경우에 유용하다.
[p.5 / Animal]
public class Animal {
public void sound() {
System.out.println("동물 울음 소리");
}
}
[p.5 / Cat]
public class Cat extends Animal {
@Override
public void sound() {
System.out.println("야옹");
}
}
1) 타입이 같을 경우 중복 제거 방법
① 메서드
② 배열, For문 사용
2) 반면 타입이 다를 경우 중복 제거 방법을 사용한다면
① 메서드 : 타입(클래스)이 다름에 따라 호출이 불가하다.
public class AnimalSoundMain1 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
soundAnimal(caw);
//soundAnimal(cat); //type(Class가)이 달라서 호출이 불가함.
//soundAnimal(dog); //type(Class가)이 달라서 호출이 불가함.
}
public static void soundAnimal(Caw caw) {
System.out.println("동물 소리 테스트 시작");
caw.sound();
System.out.println("동물 소리 테스트 종료");
}
}
② 배열, for : 타입(클래스)가 다름에 따라 같은 배열에 넣기 어렵다.
public class AnimalSoundMain2 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
Caw[] caws = {dog, cat, caw}; //type이 다름(Class 다름)
System.out.println("동물 소리 테스트 시작");
for (Caw caw : caws) {
caw.sound();
}
System.out.println("동물 소리 테스트 종료");
}
}
추상 클래스 : 상속을 목적으로 사용되고, 부모 클래스 역할을 담당, 인스턴스 존재X
추상 메서드 : 반드시 오버라이딩 해야하는 메서드
즉 각 제약들이 추가된 것으로 이해하자
1) 추상 클래스 사용 - 부모 클래스를 생성할 수 있는 문제 대비
public abstract class AbstractAnimal
- 직접 인스턴스를 추가하지 못하는 제약이 추가된 것
- class 선언시, abstract라는 키워드를 붙여주면 된다.
Animal animal = new Animal();
- 다형성을 위해 필요한 기능이지 실제 animal 인스턴스를 사용할 일은 거의 없다.
2) 추상 메서드 사용 - 매서드 오버라이딩 누락 문제 대비
public abstract void sound();
- 매서드 선언시, abstract라는 키워드를 붙여주면 된다.
- 추상 메서드가 하나라도 있는 클래스는 추상 클래스를 선언해야한다.
- 메서드 바디가 없음에 따라 불완전한 클래스로 볼 수 있으므로, 직접 생성하지 못하도록 선언해야한다.
- 상속받는 자식 클래스가 반드시 오버라이딩 해야한다.
순수 추상 클래스(모든 메서드가 추상적), 모든 메서드를 구현해야 한다.
1) 인스턴스를 생성할 수 없다.
2) 주로 다형성을 위해 사용된다.
3) 상속시 자식은 모든 메서드를 오버라이딩 해야한다.
3) 인터페이스 사용 - 다중 구현을 지원하며 순수 추상클래스와 같다.
public interface InterfaceAnimal {
void sound();
void move();
}
- class가 아닌 interface 키워드 사용
- void 앞에 public abstract 키워드 생략 가능
인터페이스는 앞서 설명한 순수 추상 클래스와 같지만, 더 나아가 적절한 제약을 준다.
또한 다중 구현을 지원하며,
인터페이스에서 멤버변수는 public/static/final이 포함되었다고 간주한다.
[p.24 / interfaceMain] 순수 추상 클래스와 동일하게 진행
public class InterfaceMain {
public static void main(String[] args) {
//InterfaceAnimal animal = new InterfaceAnimal();
Cat cat = new Cat();
Caw caw = new Caw();
Dog dog = new Dog();
soundAnimal(cat);
soundAnimal(dog);
soundAnimal(caw);
}
private static void soundAnimal(InterfaceAnimal animal) {
System.out.println("동물 울음 소리 테스트 시작");
animal.sound();
System.out.println("동물 울음 소리 테스트 종료");
}
}
- 클래스 기능 자체를 상속받는 것이 아닌 내가 직접 세부 내용을 설계하는 것을 구현이라고 한다.
[p.23 / interfaceAnimal] Interface생성
public interface InterfaceAnimal {
void sound();
void move();
}
[p.23 / Dog] 구현을 위해 implements 사용 : 부모 타입 여러개 사용 가능
public class Dog implements InterfaceAnimal{
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void move() {
System.out.println("개 이동");
}
}
*다중구현
[p.27 / interfaceA] 다중 구현 예시
public interface interfaceA {
void methodA();
void methodCommon();
}
[p.27 / interfaceB]
public interface interfaceB {
void methodB();
void methodCommon();
}
[p. 27 / Child] 다중 구현 A, B
public class Child implements InterfaceA, InterfaceB {
@Override
public void methodA() {
System.out.println("Child. methodA");
}
@Override
public void methodB() {
System.out.println("Child. methodA");
}
@Override
public void methodCommon() {
System.out.println("Child. methodCommon");
}
}
[p.28 / Main]
public static void main(String[] args) {
InterfaceA a = new Child();
a.methodA();
a.methodCommon();
InterfaceB b = new Child();
b.methodB();
b.methodCommon();
}
▶ 상속과 메모리 구조 이해
https://zoooom-in.tistory.com/61
[김영한_자바기본][10. 다형성1] 상속과 메모리 구조(p.1-23)
1. 자식 객체를 부모 참조 변수에 할당하면 부모 메서드에 접근이 가능하다. 2. 다운캐스팅은 '일시적으로' 부모 타입의 참조 변수를 자식 타입으로 형변환하는 것이다. 3. 다운 캐스팅 수행 전 ins
zoooom-in.tistory.com
'Java > [inflearn] 자바 기본' 카테고리의 다른 글
[김영한_자바기본][2. 기본형과 참조형] (보충) 메서드에 객체 전달 / 메서드에서 객체 반환 / NullPointerException (p.16-20, p.26-29) (0) | 2024.02.15 |
---|---|
[김영한_자바기본][1.클래스와 데이터] (보충) 배열 / 클래스 생성 / 배열 + 클래스 이해 (p.14, p.17, p24-27) (0) | 2024.02.14 |
[김영한_자바기본][10. 다형성1] 상속과 메모리 구조(p.1-23) (2) | 2024.02.10 |
[김영한_자바기본][9.상속] 상속과 메모리 구조(p.7-20) (0) | 2024.02.08 |
[김영한_자바기본][7. 자바 메모리 구조와 static] static 변수 및 메서드 이해 (p.15-31) (2) | 2024.02.07 |