[Java 스터디] 다형성이란 무엇일까?

🐧코딩하는 애기 펭귄·2023년 5월 23일
1

sscc Java 스터디

목록 보기
8/10
post-thumbnail

이번 포스팅에서는 객체 지향을 사용하는 궁극적인 이유인 다형성은 무엇인지, 구현 방법은 무엇인지에 대해 알아보자.

cf) 이 글은 2023년 5월 9일에 진행됐던 sscc 자바 스터디 5주차 스터디 내용을 정리한 글입니다.


다형성이란?

하나의 자료가 상황에 따라 여러 형태를 가지게 되는 것을 의미한다.

다음은 다형성을 구현하는 방법의 예시이다.

  1. 메소드 오버로딩
  2. 상속
  3. 메소드 오버라이딩
  4. 인터페이스

1. 메소드 오버로딩

함수의 이름을 같게하여 다형성을 구현하는 방법이다.

이름이 같아도
인자의 갯수, 순서, 타입이 다르면 다른 함수이다.

대표적으로 생성자 오버로딩을 사용하면, 다양한 형태의 객체 생성을 처리할 수 있다.

2. 상속

상속이란 자식 클래스가 부모 클래스의 기능을 물려 받는 것을 의미한다.

extends 키워드를 사용해서 상속 관계를 표시할 수 있다.

자식 클래스로 내려갈수록 기존 부모 클래스에다가 기능이 추가 / 구체화 된다.


상속 부수기

상속에 관해 자세히 얘기하기 전에 개념을 하나 잡고 가자.

아래 코드는 new를 사용해서 객체를 생성할 때 대표적으로 많이 쓰는 코드이다.

Cat Kitty = new Cat();
 1    2        3

이 문장은 사실 Cat Kitty; 와 Kitty = new Cat();
2개의 문장이 섞인 것이다.

위 코드를 1 2 3번 3개로 쪼개서 보면

  1. 타입(자료형)을 명시
  2. 이름(레퍼런스)을 지정
  3. new 명령어와 함께 사용할 생성자 명시

이제 다시 상속에 대해 하던 얘기를 이어가보자.

Programmer 클래스가 Person 클래스를 상속한 자식 클래스라고 하자. Programmer는 Person이다. 하지만 Person은 Programmer가 아니다. 사람은 프로그래머 뿐만이 아닌 다른 직업을 가질 수 있다.

이 말은 Programmer를 Person 타입으로 볼 수도 있다는 말이다.

이를 자바에서는 문법적으로 지원하고 있다.

Person Programmer = new Programmer();
programmer.setName("자바천재");
programmer.introduce();
programmer.job();	//에러

위 코드는 Programmer를 상위타입인 Person 타입으로 취급한 코드이다.
단, 이때는 Person 타입으로 취급하는만큼 Programmer에만 있는 메소드는 사용이 불가능하다.

3. 메소드 오버라이드

영어로 Overide는 덮어쓰기의 의미이다.

상속 관계에 있는 두 클래스에서 메소드가 중복정의(오버라이드)되면, 하위 클래스에 우선 순위가 생겨서 실행된다.

예시 코드를 보며 이해해보자.

class Person {
    String name;
    
    Person(String name) {
    	this.name = name;
    }
    
    Person() {};

    void setName(String name) {
        this.name = name;
    }

    void introduce() {
        System.out.println("저는 " + name + "입니다.");
    }
}


class Programmer extends Person {

	Programmer(String name) {
    	super(name);
    }
    
    void job() {
        System.out.println(this.name + "는 코딩하는 중");
    }

    @Override	// 어노테이션 부분
    void introduce() {
        System.out.println("저는 " + "개발자 " + name + "입니다.");
    }
}


public class Main {
    public static void main(String[] args) {
        Programmer programmer = new Programmer();
        programmer.setName("자바천재");
        programmer.introduce();
        programmer.job();
    }
}

예시 코드를 보면 introduce() 메소드가 Person과 Programmer 클래스 둘 다 존재한다.
그렇지만 하위 클래스에 우선 순위가 생겨 실행되기 때문에 실행 결과가 Programmer 클래스의 introduce()가 실행된 것이다.

어노테이션

메소드 오버라이딩을 한 코드 윗부분을 자세히 보면 @Override 라는 문장이 존재한다.
이와 같은 문장을 어노테이션(annotation)이라고 한다.

어노테이션은 일반적인 주석과는 다르다.
어노테이션으로 적은 이 문장은 오버라이드가 아닌 경우에 컴파일 에러를 발생시킨다.

따라서 어노테이션을 사용하면 나와 컴파일러가 예상하지 못한 오류에 대해서 잡아낼 수 있기 때문에 보다 안전한 프로그래밍과 빠른 디버깅이 가능하다.

상속 관계에서 생성자 (super)

자식 클래스에서 부모 클래스의 생성자를 호출하는 방법은
super()를 사용하면 된다. 괄호 안에 있는 값을 매개변수로 하는 부모 클래스의 생성자를 호출하는 문장이다.

단, super()는 사용할 때 한 가지 유의점이 있는데,
반드시 자식 클래스의 생성자 첫 문장에서만 존재해야 한다는 것이다.
그렇기 때문에 this() 생성자와 동시에 사용할 수 없다.

이쯤되면 한 가지 의문점이 생긴다.
자식 클래스는 부모 클래스를 물려받는다고 했는데, 그럼 부모 클래스가 생성되어야 하는 거 아닌가?
그럼 부모 클래스의 생성자를 호출 안 하면 어떻게 되는 거지?

예전에 올린 포스팅에서 생성자를 따로 정의하지 않을 경우, 기본 생성자를 자동으로 넣어준다고 그랬었다.

super도 마찬가지다. 자식 클래스 생성자에 첫 문장에 super를 따로 명시하지 않은 경우, 매개변수가 void형인 super()가 자동으로 삽입되어 실행된다.

상속을 사용할 때 많이 실수하는 부분이니 부모 클래스에 생성자가 존재한다면, 자식 클래스는 super를 명시하는 것을 습관화하자.


오늘은 이렇게 다형성을 구현하는 3가지 방법을 알아보았다.

객체지향의 꽃이라고 불릴만큼 다형성은 매우 중요한 개념이니 귀찮더라도 다형성을 구현할 수 있는 상황이라면 꾸준히 구현하려고 노력해보자.

0개의 댓글

관련 채용 정보