자바 기초 다형성

웅평·2023년 12월 4일

다형성 (Polymorphism)

  • 다형성이란 여러 개를 의미하는 poly와 형태 또는 실체를 의미하는 morphism의 결합어로, 하나의 객체가 여러 가지 형태를 가질 수 있는 것을 의미한다.

다형성의 장점

  • 유지보수 : 여러 객체를 하나의 타입으로 관리할 수 있어 유지보수가 용이하다.
  • 재사용성 : 객체의 재사용이 쉬워 재사용성이 높아진다.
  • 느슨한 결합 : 클래스 간의 의존성을 줄여 확장성은 높아지고 결합도는 낮아진다.

다형성의 조건

  • 상위 클래스와 하위 클래스는 상속 관계여야 한다.
  • 다형성이 보장되기 위해 오버라이딩(하위 클래스 메서드의 재정의)이 반드시 필요하다.
  • 자식 클래스의 객체가 부모 클래스의 타입으로 형변환(업캐스팅)해야 한다.
// 부모 클래스
public class Camera {
    public String name;

    public Camera() {
       this("카메라");
    }

    protected Camera(String name) {
        this.name = name;
    }

    public void takePicture() {
        // 사진 촬영
        System.out.println(this.name + " 사진을 촬영합니다.");
    }

    public void recordVideo() {
        // 동영상 촬영
        System.out.println(this.name + " 동영상을 녹화합니다.");
    }

    public void showMainFeature() {
        System.out.println(this.name + "의 주요 기능 : 사진 촬영, 동영상 녹화");
    }
}

// 상속을 못하게 final
public final class ActionCam extends Camera {
    // 렌즈를 바꾸지 못하게 하는 방법
    // public final String lens = "광각렌즈";
    public final String lens;

    // final를 추가해서 직접 값을 처리하는 경우도 있고 생성자를 총해서 처리하는 방법도 있다
    public ActionCam() {
        super("액션 카메라");
        lens = "광각렌즈";
    }

    public final void makeVideo() {
        System.out.println(this.name + " : " + this.lens + " 비디오 제작합니다");
    }
}

// Carmera의 자식 클래스
public class FactoryCam extends Camera {

    public FactoryCam() {
        super("공장 카메라");
    }

    public void detecFire() {
        // 화재 감지
        System.out.println("화재 감지합니다");
    }

    // 메소드 오버라이딩
    public void showMainFeature() {
        System.out.println(this.name + "의 주요 기능 : 화재 감지");
    }

    public void recordVideo() {
        // 동영상 촬영
        super.recordVideo();
        detecFire();
    }
}

public class SpeedCam extends Camera {
    public SpeedCam() {
        super("과속닥속 카메라");
    }

    public void checkSpeed() {
        // 속도 체크
        System.out.println("속도를 측정합니다");
    }

    public void recognizeLicensePlate() {
        // 번호 인식
        System.out.println("번호판 인식");
    }

    // 이 소스코드를 컴퓨터가 알아볼수 있는 형태로 바꾸는 것을 컴파일 그 역할을 하는게 컴파일러
    @Override // annotation(주석) 평소 쓰는 주석이랑 다르다
    public void showMainFeature() {
        System.out.println(this.name + "의 주요 기능 : 속도 측정, 번호 인식");
    }

    public void takePicture() {
        // 사진 촬영
        // 중복된 부분을 사용, 상속을 하는 의미가 없어짐
        // System.out.println(this.name + " 사진을 촬영합니다.");
        super.takePicture();
        checkSpeed();
        recognizeLicensePlate();
    }
}
public class _14_Polymorphism {
    public static void main(String[] args) {
        // 다형성

        // class Person : 사람
        // class Student extends Person : 학생 (학생은 사람이다)
        // class Teacher extends Person : 선생님 (선생님은 사람이다)

        /*Camera camera = new Camera();
        FactoryCam factoryCam = new FactoryCam();
        SpeedCam speedCam = new SpeedCam();*/

        // 다형성 이용: 자식클래스 이름대신 부모클래스 이름으로 형태가 서로 다른 객체를 형성가능
        Camera camera = new Camera();
        Camera factoryCam = new FactoryCam();
        Camera speedCam = new SpeedCam();

        camera.showMainFeature();
        factoryCam.showMainFeature();
        speedCam.showMainFeature();

        System.out.println("-------------");
        Camera[] cameras = new Camera[3];
        cameras[0] = new Camera();
        cameras[1] = new FactoryCam();
        cameras[2] = new SpeedCam();

        for (Camera cam: cameras) {
            cam.showMainFeature();
        }

        System.out.println("-------------");

        // 오류 나는 이유는 정의할 떄 Camera클래스(부모)로 했기 때문이다
        // 그렇기 때문에 부모클래스에 있는 메소드만 사용가능
        // speedCam.checkSpeed();
        // factoryCam.detecFire();

    }
}

상위 클래스 타입의 참조 변수로 하위 클래스의 객체를 참조하는 다형성의 핵심적인 부분이다.
그러나, 하위 클래스 타입으로 상위 클래스의 객체를 참조하는 것은 허용되지 않는다.

참조 변수의 형 변환

  • 자바에서는 기본 자료형의 형 변환도 가능하지만, 참조 변수도 형 변환이 가능하다.
  • 참조 변수의 형 변환은 사용할 수 있는 멤버의 개수를 조절하는 것이다.

형 변환을 위한 조건

  • 서로 상속관계에 있는 상위 클래스 : 하위 클래스 사이에만 형 변환이 가능하다.
  • 업 캐스팅(하위 클래스 타입에서 상위 클래스 타입으로 형 변환)은 형 변환 연산자를 생략할 수 있다.
  • 다운 캐스팅(상위 클래스에서 하위 클래스 타입으로 변환)은 형 변환 연산자를 반드시 작성해야 한다.
		FactoryCam factoryCam = new FactoryCam();
 		// 업 캐스팅 () 생략 가능
       Camera camera  = (Camera) factoryCam;

        // 다운 캐스팅 () 생략 불가능
        FactoryCam factoryCam = (FactoryCam)camera;
 

instanceof 연산자

  • instanceof 연산자는 참조 변수의 형 변환이 가능한 지의 여부를 boolean 타입으로 확인할 수 있는 자바의 문법 요소이다.
  • 즉, 업 캐스팅 또는 다운 캐스팅이 가능한 지를 검사하는 것이다.
  • 프로젝트의 규모가 커지고, 클래스가 많아지면 캐스팅 가능 여부를 판단하기 어려워진다. 이러한 문제를 해결해 주는 것이 바로 instanceof 연산자이다.

 // 위 오류를 해결하는 방법 = 형변환을 통해서 메소드에 접근
        // instanceof를 사용 : 이 객체가 어떤 클래스의 객체인지 확인
        if (camera instanceof Camera) { // camera의 객체가 Camera로 부터 만들어진 객체라면
            System.out.println("카메라입니다");
        }

        if (factoryCam instanceof FactoryCam) { // factoryCam이 FactoryCam의 인스턴스인지
            ((FactoryCam)factoryCam).detecFire();
        }

        if (speedCam instanceof SpeedCam) {
            ((SpeedCam)speedCam).checkSpeed();
            ((SpeedCam) speedCam).recognizeLicensePlate();
        }

        // 자바는 기본적으로 Object라는 클래스를 상속
        // 어떤 객체든 모든 클래스 객체를 넣을 수 있다
        Object[] obj = new Object[3];
        obj[0] = new Camera();
        obj[1] = new SpeedCam();
        obj[2] = new FactoryCam();

국비학원에서 배운것과 따로 공부한 것을 정리한 것입니다

참고
나도코딩 유튜브

0개의 댓글