# 멤버 메소드 설정

## 상속 관계에서 메소드 설정

상위 클래스에서 멤버 메소드를 만들 때 가장 중요하게 생각해야 하는 부분은 **재정의** 여부이다. 재정의가 무엇인지 예제를 통해 알아본다.

### 데모 1 : 메소드 재정의가 필요한 이유

휴대폰 관리 앱을 개발중인 프로젝트 팀에서 개발 생산성 향상을 위해 상속 구조로 클래스를 구현하기로 하였고, 이를 위해 최상위 클래스인 전화기(Phone)를 다음과 같이 설계했다고 가정해보자.

{% code title="Phone.java" %}

```java
public class Phone {
    protected String number;
    
    public void call() { /* 화 코드 */ }
    public void sms() { /* 메세지 코드 */ }
}
```

{% endcode %}

전화기(Phone)은 기본적으로 다음 두 가지 기능이 작동해야 한다.

* 통화(call) 기능
* 메세지(sms) 기능

하지만 상세 클래스(Galaxy20s , IPhone12)를 구현하기 전까지는 해당하는 기능이 필요하다는 사실은 알지만 구체적으로 어떻게 작동하는지 설명할 수 있는 방법이 없다. 즉, 해당하는 기능의 **명세**만 필요한 상황이라고 볼 수 있다. 따라서 내용은 작성할 수 없고, 작성하더라도 매우 추상적인 내용이 작성되어야 한다.

{% code title="Phone.java" %}

```java
public class Phone {
    protected String number;
    
    public void call() { 
        System.out.println("통화 기능 실행");
    }
    public void sms() {
        System.out.println("메세지 발송 기능 실행");
    }
}
```

{% endcode %}

그렇다면 하위 클래스들을 만들 때 Phone 클래스의 call과 sms 메소드를 그대로 이용해야 할까?

{% tabs %}
{% tab title="Galaxy20s" %}
{% code title="Galaxy20s.java" %}

```java
public class Galaxy20s extends Phone{
    
}
```

{% endcode %}
{% endtab %}

{% tab title="IPhone12" %}
{% code title="IPhone12.java" %}

```java
public class IPhone12 extends Phone {
    
}
```

{% endcode %}
{% endtab %}

{% tab title="InheritExample04" %}
{% code title="InheritExample04.java" %}

```java
public class InheritExample04 {
    public static void main(String[] args){
        Galaxy20s galaxy = new Galaxy20s();
        galaxy.call();
        galaxy.sms();
        
        IPhone12 iphone = new IPhone12();
        iphone.call();
        iphone.sms();
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

단순하게 위와 같이 상속을 받았다고 가정해보면, Galaxy20s와 IPhone12 클래스 모두 call, sms 기능을 가지고 있지만 아무런 차이점도 가질 수 없다. 상속을 통해 중복되는 내용을 없에긴 했지만 정작 차이점을 가질 수 없다는 것이다. 그렇다고 다른 이름으로 구현할 수도 없는 상황인데, 이를 해결하기 위해서는 저장 형태를 이해할 필요가 있다.

![InheritExample04 메모리 예상도](https://4208234536-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M_TNZwLuHV9ipYLbvRq%2F-MeTEg55wYoYZUwjnnL_%2F-MeTGdpGFoq1baRQlVjH%2Fimage.png?alt=media\&token=1135c024-1a66-4a67-aa9a-25bf945f9c81)

위의 그림대로라면 galaxy와 iphone에서 call 메소드를 부르면 각자 자신이 상속받은 Phone 클래스의 call 메소드를 호출하게 된다. 따라서 galaxy와 iphone에서 call 메소드를 부르면 차이점을 가질 수 없게 되는데, 이를 해결하는 방법은 동일한 이름으로 메소드를 this에 하나 더 만드는 것이다.

### 데모 2 : 메소드를 재정의한 경

{% tabs %}
{% tab title="Galaxy20s" %}
{% code title="Galaxy20s.java" %}

```java
public class Galaxy20s extends Phone{
    public void call(){
        System.out.println("갤럭시20s 통화 기능 실행");
    }
    public void sms(){
        System.out.println("갤럭시20s 메세지 발 기능 실행");
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="IPhone12" %}
{% code title="IPhone12.java" %}

```java
public class IPhone12 extends Phone {
    public void call(){
        System.out.println("아이폰12 통화 기능 실행");
    }
    public void sms(){
        System.out.println("아이폰12 메세지 발 기능 실행");
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="InheritExample05" %}
{% code title="InheritExample05.java" %}

```java
public class InheritExample05 {
    public static void main(String[] args){
        Galaxy20s galaxy = new Galaxy20s();
        galaxy.call();
        galaxy.sms();
        
        IPhone12 iphone = new IPhone12();
        iphone.call();
        iphone.sms();
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

위 예제에서 Phone 클래스는 동일하게 사용하였다. 실행해보면 결과가 데모1 과 다른 것을 확인할 수 있으며, 그림으로 구조를 살펴보면 다음과 같다.

![InheritExample05 메모리 예상도](https://4208234536-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M_TNZwLuHV9ipYLbvRq%2F-MeTEg55wYoYZUwjnnL_%2F-MeTHz66I0qrZczJC6ZL%2Fimage.png?alt=media\&token=0628fb3c-1d7c-45aa-b71c-0878e6d99358)

모든 객체는 자신(this)이 가진 구성요소부터 찾도록 되어 있고, 찾으면 더이상의 탐색을 수행하지 않기 때문에 Phone 클래스의 call과 sms는 더이상 실행되지 않고 Galaxy20s와 IPhone12 클래스의 call과 sms 메소드가 실행되는 것을 확인할 수 있다. 마치 Phone의 call, sms 메소드가 수정된 듯한 느낌을 받게 되며, 이를 **메소드 재정의(Method Override)**&#xB77C; 부른다.

![모든 객체는 자신(this)이 가진 구성요소를 먼저 찾는다. 색칠한 부분이 해당 영역이다.](https://4208234536-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M_TNZwLuHV9ipYLbvRq%2F-MeTEg55wYoYZUwjnnL_%2F-MeTIeBaQIXO3-SE3Y7G%2Fimage.png?alt=media\&token=3f88d1ea-1cbc-4567-90dd-97e3e9cc0451)

### 데모 3 : 메소드 재정의 금지

메소드 재정의를 원치 않는 경우 `final` 키워드를 사용하여 재정의를 금지할 수 있다.&#x20;

{% content-ref url="../final" %}
[final](https://docs.sysout.co.kr/base-language/java/advanced/final)
{% endcontent-ref %}

### 데모 4 : 메소드 재정의 강제

메소드 재정의를 반드시 수행해야 하는 경우가 있다. 추상 클래스에 대해서 먼저 살펴봐야 한다.

{% content-ref url="../abstract/abstract-class" %}
[abstract-class](https://docs.sysout.co.kr/base-language/java/advanced/abstract/abstract-class)
{% endcontent-ref %}
