티스토리 뷰
1. 메서드 오버라이딩
package poly.overriding;
public class Parent {
public String value = "parent";
public void method() {
System.out.println("Parent.method");
} }
package poly.overriding;
public class Child extends Parent {
public String value = "child";
@Override
public void method() {
System.out.println("Child.method");
}
}
=> Child에서 Parent의 메서드를 오버라이딩 하였다.
package poly.overriding;
public class OverridingMain {
public static void main(String[] args) {
//자식 변수가 자식 인스턴스 참조
Child child = new Child();
System.out.println("Child -> Child");
System.out.println("value = " + child.value); child.method();
//부모 변수가 부모 인스턴스 참조
Parent parent = new Parent();
System.out.println("Parent -> Parent");
System.out.println("value = " + parent.value); parent.method();
//부모 변수가 자식 인스턴스 참조(다형적 참조)
Parent poly = new Child();
System.out.println("Parent -> Child");
System.out.println("value = " + poly.value); //변수는 오버라이딩X poly.method(); //메서드 오버라이딩!
}
}
=> Child -> Child
=> value = child
=> Child.method
=> Parent -> Parent
=> value = parent
=> Parent.method
=> Parent -> Child
=> value = parent (변수는 오버라이딩 되지 않으므로 parent로 나오고)
=> Child.method (메서드 오버라이딩으로 child method를 우선으로 호출)
=> poly 변수는 Parent 타입으로 method를 호출 했을 때 오버라이딩 된 메서드가 항상 우선권을 가지므로 Parent.method()가 아닌 Child.method()가 실행된다. 기존 기능을 하위 타입에서 새로운 기능으로 재정의하여 사용할 수 있다.
2. 다형성 활용법
package poly.ex2;
public class Animal {
public void sound() {
System.out.println("동물 울음 소리"); }
}
=> 최상위 부모로 Animal 클래스를 만들고 sound 메서드를 정의해놓고 하위 클래스에서 재정의하여 사용할 수 있다.
package poly.ex2;
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("멍멍");
}
}
public class Cat extends Animal {
@Override
public void sound() {
System.out.println("냐옹");
}
}
public class Caw extends Animal{
@Override
public void sound() {
System.out.println("음매");
}
}
package poly.ex2;
public class AnimalPolyMain1 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
soundAnimal(dog);
soundAnimal(cat);
soundAnimal(caw);
}
//동물이 추가 되어도 변하지 않는 코드
private static void soundAnimal(Animal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
=> soundAnimal 메서드의 매개변수 타입을 공통 부모인 Animal 클래스로 받아서 sound() 메서드를 호출하게 되면 동물이 추가 되어도 변하지 않는 코드가 된다. 구체적인 클래스를 참조하는 것이 아니라 Animal이라는 추상적인 부모를 참조할 수 있기 때문이다. 만약에 사자가 추가 된다고 하더라도 객체 생성하고 그 객체를 매개변수로 갖는 메서드를 호출하기만 하면 된다.
=> 실행결과
- 동물 소리 테스트 시작
- 멍멍
- 동물 소리 테스트 종료
- 동물 소리 테스트 시작
- 냐옹
- 동물 소리 테스트 종료
- 동물 소리 테스트 시작
- 음매
- 동물 소리 테스트 종료
=> animal.sound()로 호출하게 되면 Dog, Cat, Caw 어떤 동물이든 부모의 메서드를 재정의 한 자식의 메서드를 호출하여 사용할 수 있으므로 동물이 바뀌고 추가되어도 매개변수와 메서드 추가 없이 단일한 코드로 활용할 수 있다.
package poly.ex2;
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};
//Animal[] animalArr = new Animail[]{dog, cat, caw};
//변하지 않는 부분
for (Animal animal : animalArr) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
}
=> Animal 타입의 배열을 만들고 여러 타입의 객체를 참조한다.
=> 배열을 사용한 중복 제거로 실행 결과는 위와 동일.
3. 추상 클래스와 추상 메서드
- 추상 클래스: 부모 클래스는 제공하지만 실제로 생성하면 안되는 클래스로 추상적인 개념을 제공하는 클래스. 상속을 목적으로 사용되며 인스턴스를 만들 수 없다.
- 추상 메서드: 부모 클래스를 상속 받는 자식 클래스가 반드시 오버라이딩 해야 하는 메서드를 부모 클래스에 정의할 수 있다. 추상 메서드가 하나라도 있는 클래스는 추상 클래스가 되어야 한다. 추상 메서드는 상속을 받게 된 자식 클래스가 반드시 오버라이딩하여 사용해야 한다.
package poly.ex3;
public abstract class AbstractAnimal {
//인스턴스를 생성할 수 없는 추상 메서드로 반드시 자식이 오버라이딩하여 사용해야 한다.
public abstract void sound();
//인스턴스를 생성할 수 있는 그냥 메서드로 자식이 오버라이딩 하지 않아도 된다.
public void move() {
System.out.println("동물이 움직입니다.");
}
}
=> 추상 메서드는 인스턴스를 생성할 수 없고 자식클래스가 반드시 오버라이딩하여 사용해야만 한다.
package poly.ex3;
public class Cat extends AbstractAnimal {
@Override
public void sound() {
System.out.println("냐옹");
}
}
public class Caw extends AbstractAnimal {
@Override
public void sound() {
System.out.println("음매");
}
}
public class AbstractMain {
public static void main(String[] args) {
//추상클래스 생성 불가
//AbstractAnimal animal = new AbstractAnimal();
Dog dog = new Dog();
Cat cat = new Cat();
Caw caw = new Caw();
cat.sound();
cat.move();
soundAnimal(cat);
soundAnimal(dog);
soundAnimal(caw);
}
//동물이 추가 되어도 변하지 않는 코드
private static void soundAnimal(AbstractAnimal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
} }
=> 실행결과
냐옹 //cat.sound();
동물이 움직입니다. //cat.move();
- 동물 소리 테스트 시작
- 냐옹
- 동물 소리 테스트 종료
- 동물 소리 테스트 시작
- 멍멍
- 동물 소리 테스트 종료
- 동물 소리 테스트 시작
- 음매
- 동물 소리 테스트 종료
4. 인터페이스
public interface InterfaceAnimal {
void sound();
void move();
}
=> public abastract를 생략할 수 있는 추상 메서드의 집합, 인터페이스
=> 특징1: 인스턴스를 생성할 수 없고, 상속 시 모든 메서드를 오버라이딩 해야 한다.
=> 특징2: 인터페이스에서의 멤버변수는 public, static, final이 모두 포함되었다고 간주된다.
public class Dog implements InterfaceAnimal {
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void move() {
System.out.println("개 이동");
}
}
=> extends 대신 implements 키워드를 사용한다. 인터페이스의 추상메서드를 오버라이딩하여 사용한다.
public class InterfaceMain {
public static void main(String[] args) {
Dog dog = new Dog();
soundAnimal(dog);
}
//동물이 추가 되어도 변하지 않는 코드
private static void soundAnimal(InterfaceAnimal animal) {
System.out.println("동물 소리 테스트 시작");
animal.sound();
System.out.println("동물 소리 테스트 종료");
}
}
=> 실행결과
동물 소리 테스트 시작
멍멍
동물 소리 테스트 종료
=> 상속과 구현의 차이
상속은 부모의 기능을 물려 받는 것이 목적이고, 인터페이스의 구현은 물려받을 수 있는 기능은 없고 인터페이스에 정의한 모든 메서드를 자식이 오버라이딩해서 구현해야만 한다.
=> 다중 구현
인터페이스를 구현하는 곳에서 해당 기능을 모두 구현해야 한다.
public interface InterfaceA {
void methodA();
void methodCommon();
}
public interface InterfaceB {
void methodB();
void methodCommon();
}
public class Child implements InterfaceA, InterfaceB {
@Override
public void methodA() {
System.out.println("Child.methodA");
}
@Override
public void methodB() {
System.out.println("Child.methodB");
}
@Override
public void methodCommon() {
System.out.println("Child.methodCommon");
}
}
=> implements InterfaceA, InterfaceB와 같이 다중 구현을 할 수 있다.
=> methodCommon()의 경우 양쪽 인터페이스에 다 있지만 같은 메서드이기 때문에 구현은 하나만 하면 된다.
public class InterfaceMain {
public static void main(String[] args) {
InterfaceA a = new Child();
a.methodA();
a.methodCommon();
InterfaceB b = new Child();
b.methodB();
b.methodCommon();
}
}
실행결과
Child.methodA
Child.methodCommon
Child.methodB
Child.methodCommon
'JAVA' 카테고리의 다른 글
[멀티스레드와 동시성] - 1. 프로세스와 스레드 (0) | 2024.07.25 |
---|---|
자바 채팅 프로그램 (0) | 2024.05.29 |
다형성1 (0) | 2024.01.07 |
1. JDK, JRE, JVM (0) | 2023.11.29 |
JAVA | null과 "" | 개념 (2) | 2023.08.03 |