다형성(Polymorphism)이란?

원혜린·2021년 7월 16일
2

다형성은 "여러 객체에게 동일한 명령을 내렸을 때 서로 다르게 반응하는 현상"을 의미합니다.

예를 들어 울음소리를 고양이에게 요청하면 보통 "야옹~"으로 반응하지만, 소에게 요청하면 "음메~" 이렇게 다르게 반응합니다.

또는 전화를 많이 하시는 아빠에게 스마트폰은 뭐야?라고 물어보면 통화하는 기기라고 반응하지만, SNS를 많이 하는 친구(=성이 박씨)에게 스마트폰은 SNS이라고 반응할 수 있게 되겠죠.

이렇게 동일한 요청이지만 다르게 반응하는 "다형성"을 자바에서도 구현할 수 있는데요, 보통 다형성을 구현하는 법에는 아래와 같이 4가지가 있습니다.

1) 인터페이스(interface)
2) 추상클래스(abstract)
3) 메소드 오버라이딩
4) 메소드 오버로딩

1) 인터페이스를 통한 다형성

먼저 인터페이스를 통한 다형성은 인터페이스를 통해 구현한 클래스에게 어떤 인터페이스에 집중하라고 말할 수 있게 됩니다.

소스 코드로 살펴보면 FatherPhone, ParkPhone은 모두 Callable, SNSable 인터페이스를 통해 구현했지만 실제 사용할 때 fp라는 변수의 타입을 Callable 인터페이스로 특정 짓는다면 fp는 SNSable에 있는 instagram() 함수를 사용할 수 없게 됩니다.

이렇게 특정 인터페이스에 집중한 클래스를 만들 수 있게 됩니다.

package test;

interface Callable{
    void call(String phoneNum);
}
interface SNSable{
    String instagramId = "myId";
    void instagram();
    void tiktok();
}
class FatherPhone implements Callable, SNSable{
    public void call(String phoneNum) {
        System.out.println(phoneNum + " 으로 전화를 겁니다.");
    }
    public void instagram() {
    }
    public void tiktok() {
    }
}
class ParkPhone implements Callable, SNSable{
    public void call(String phoneNum) {
        System.out.println(phoneNum + "으로 전화를 겁니다.");
    }
    public void instagram() {
        System.out.println("인스타그램 계정:" +instagramId);
    }
    public void tiktok() {
        System.out.println("스마트폰으로 틱톡을 주로 사용해");
    }
}
public class Test {
    public static void main(String[] args) {
        Callable fp = new FatherPhone();
        System.out.println("아빠는 스마트폰으로 전화를 주로 사용해");
        fp.call("01012345678");
        //fp.instagram(); // 사용 불가
        
        ParkPhone pp = new ParkPhone();
        System.out.println("박씨는 스마트폰으로 전화를 주로 사용해");
        pp.instagram();
        pp.call("0101111111");
    }
}

2) 추상 클래스를 통한 다형성

추상 메소드는 선언부만 있고 구현부가 없는 메소드입니다. 앞서 보신 인터페이스의 메소드 형태와 같다고 보시면 됩니다. 이러한 추상 메소드를 포함한 클래스인 추상 클래스를 이용한 다형성은 추상 클래스를 실제로 상속받은 구현체에게 서로 다른 반응을 이끌어 낼 수 있습니다.

만약 인스타그램이 이미지만 올릴 수 있고 틱톡이 영상만 올릴 수 있는 SNS라고 가정한다면, 같은 SNS라고 하더라도 업로드 기능은 다른 모습으로 구현되어야하겠죠.

이렇게 추상 클래스를 이용하여 다른 모습으로 구현하는 다형성을 구현할 수 있습니다.

package test;

abstract class SNS{
    String defaultUploadFileType = "";
    void login(){};
    abstract void upload(String uploadFileType);
}

class Instagram extends SNS {
    String defaultUploadFileType = "image";
    void login() { /*로그인*/}
    void upload(String uploadFileType){
        if(uploadFileType != defaultUploadFileType){
            System.out.println("(에러) 이미지만 업로드 가능합니다.");
        }else{
            System.out.println("정상적으로 업로드 되었습니다.");
        }
    }   
}

class Tiktok extends SNS {
    String defaultUploadFileType = "video";
    void login() { /*로그인*/}
    void upload(String uploadFileType){
        if(uploadFileType != defaultUploadFileType){
            System.out.println("(에러) 비디오만 업로드 가능합니다.");
        }else{
            System.out.println("정상적으로 업로드 되었습니다.");
        }
    }   
}

public class Test {
    public static void main(String[] args) {
        Instagram i = new Instagram();
        i.upload("image");
        Tiktok tt = new Tiktok();
        tt.upload("image");
    }
}

3) 메소드 오버라이딩을 통한 다형성

메소드 오버라이딩과 메소드 오버로딩을 통한 다형성이 남았는데요

  • 오버라이딩(Overriding): 같은 상속 관계에 있는 클래스 간에 같은 이름의 메소드를 재정의
public class SNS{
    public void upload(){
        System.out.println("기본 업로드 기능.");
    }
} 
class Tiktok extends SNS{
    public void upload(){
        System.out.println("틱톡만의 업로드 기능!!");
    }
}

4) 메소드 오버로딩을 통한 다형성

  • 오버로딩(Overloading): 같은 이름의 함수를 매개변수의 유형과 개수을 다르게 하여 다양한 유형의 호출에 응답
class SNS{
    public void upload(){
        System.out.println("정상적으로 업로드 되었습니다.");
    }
    public void upload(int cnt){
        for(int i=0; i < cnt; i++){
            System.out.println("정상적으로 업로드 되었습니다.");
        }
    }
}

[오늘의 심화 개념]

파이썬에서도 메소드 오버로딩이 동일하게 작용할까요?
정답은 NO 입니다!

자바에서는 메소드 오버로딩이 가능하지만 파이썬에서는 메소드 오버로딩을 정식으로 지원하지 않는다는 점 기억해주세요!

아래와 같은 코드가 있다면 첫번째 upload 메소드는 무시되고, 두번째 upload 메소드만 유지됩니다.
그래서 upload 메소드 호출시 cnt 파라미터가 없으면 에러가 나게됩니다!

class SNS:
    def __init__(self, upload_file_type):
        self.upload_file_type = upload_file_type

    def upload(self):
        print('정상적으로 업로드 되었습니다.')

    def upload(self, cnt):
    	for i in range(0, cnt):
        	print('정상적으로 업로드 되었습니다.')
profile
백엔드 개발자

1개의 댓글

다형성 예시 찰떡이네요 잘 보고 갑니다 ~~ ^^

답글 달기