과제 6 + 7. 우리가 핸드폰을 객체 지향 세상에서 산다면?

수원 개발자·2024년 4월 11일

스진초_과제

목록 보기
6/12
post-thumbnail

객체를 늘 먼저 생각하고, 내 코드가 진짜 객체 지향스러운지 고민해주세요

본 과제는 다형성에 초점을 둔 과제입니다.

  • 아래 채점 기준을 참고하여, 채점 기준에 부합하도록 구현해주세요.
  • 객체..객체...객체.... 속으로 외치면서 하기!!

고려해보시면 좋을 기준

  • 클래스 간 상/하위 관계(일반 클래스, 추상 클래스, 인터페이스 중 1개)를 활용합니다.
  • 오버라이드를 적절히 활용하면 좋겠죠?
  • 메소드 이름이 명확하면 좋겠습니다! (메소드명을 읽었을 때, 코드를 이해하는 데 모호하지 않다)
  • Readme에 자신이 구현한 코드와 클래스를 설계한 이유를 설명합니다. (자유 형식)

1차 코드

처음에는 먼저 생각한 것은 phone이라는 인터페이스를 생성 후, 각 객체들을 개별적으로 생각해서 Samsung, Apple 클래스를 만들어서 이를 implements해와서 재정의하는 것으로 생각했다. 이렇게 하면 클래스 간 상/하위 관계가 명확하고 오버라이드를 통해 재정의하기 때문에 좋은 객체 코드라고 생각했다.

package phone;

public interface Phone {
    public void buyPhone();

    public void turnOnPhone();
}
package phone;

public class SamsungPhone implements Phone{

    String name;
    String phoneName;

    public SamsungPhone(String name, String phoneName) {
        this.name = name;
        this.phoneName = phoneName;
    }

    @Override
    public void buyPhone() {
        System.out.println(name + "님이 " + phoneName+"을 샀습니다.");
    }

    @Override
    public void turnOnPhone() {
        System.out.println(name + "님이 " + phoneName+"을 켰습니다.");
        System.out.println("*** 폰 켜지는 중 ***");
    }
}
package phone;

public class ApplePhone implements Phone {
    String name;
    String phoneName;

    public ApplePhone(String name, String phoneName) {
        this.name = name;
        this.phoneName = phoneName;
    }

    @Override
    public void buyPhone() {
        System.out.println(name + "님이 " + phoneName+"을 샀습니다.");
    }

    @Override
    public void turnOnPhone() {
        System.out.println(name + "님이 " + phoneName+"을 켰습니다.");
        System.out.println("@@@ 폰 켜지는 중 @@@");
    }
}

이렇게 각 객체를 구성하고 메인 메서드를 실행했다.

import phone.ApplePhone;
import phone.SamsungPhone;

public class Main {
    public static void main(String[] args) {
        SamsungPhone samsungPhone = new SamsungPhone("재용", "삼송폰");

        samsungPhone.buyPhone();
        samsungPhone.turnOnPhone();

        System.out.println();

        ApplePhone applePhone = new ApplePhone("잡스", "사과폰");

        applePhone.buyPhone();
        applePhone.turnOnPhone();
    }

}

각 구매자와 제품 명은 그때 그때 달라질 수 있고 이들의 정보를 담으면 좋겠다고 생각해서 생성자를 통해 만들 수 있게 했고 이를 통해 메서드에서 출력할 수 있게 생각했다. 그런데 이들을 생각해보니 사실상 SamsungPhone과 ApplePhone의 코드는 겹치는 부분이 많다. 그렇기 때문에 인터페이스나 추상 클래스를 통해 좀 더 간결하게 만들 수도 있을 것 같다는 생각을 했다.

공통 규약인 추상 클래스를 통해 이를 간결하게 해보자!! 가 2차 코드의 목표가 되었다.

2차 코드

ApplePhone과 SamsungPhone 클래스의 메서드가 거의 동일하다는 점을 고려한다면, 중복 코드를 줄일 수 있는 방법이 필요하다. 이를 위해서는 공통된 기능을 가진 상위 클래스나 인터페이스를 도입하면 된다.

간단한 방법 중 하나는 추상 클래스를 활용하는 것이다. Phone 인터페이스를 구현하는 추상 클래스를 만들고, 그 안에 공통된 기능을 가진 메서드를 구현할 수 있다. 그리고 SamsungPhone과 ApplePhone은 이 추상 클래스를 상속받도록 구성하면 된다.

package phone;

public interface Phone {
    void buyPhone();
    void turnOnPhone();
}
** 추가된 추상클래스 **
package phone;

public abstract class AbstractPhone implements Phone {
    String name;
    String phoneName;

    public AbstractPhone(String name, String phoneName) {
        this.name = name;
        this.phoneName = phoneName;
    }

    @Override
    public void buyPhone() {
        System.out.println(name + "님이 " + phoneName + "을 샀습니다.");
    }

    @Override
    public void turnOnPhone() {
        System.out.println(name + "님이 " + phoneName + "을 켰습니다.");
    }
}
package phone;

public class SamsungPhone extends AbstractPhone {

    public SamsungPhone(String name, String phoneName) {
        super(name, phoneName);
    }

    @Override
    public void turnOnPhone() {
        super.turnOnPhone();
        System.out.println("*** 폰 켜지는 중 ***");
    }
}
package phone;

public class ApplePhone extends AbstractPhone {

    public ApplePhone(String name, String phoneName) {
        super(name, phoneName);
    }

    @Override
    public void turnOnPhone() {
        super.turnOnPhone();
        System.out.println("@@@ 폰 켜지는 중 @@@");
    }
}

이렇게 하면 AbstractPhone 클래스에 공통 기능을 구현함으로써 중복을 제거할 수 있고, SamsungPhone과 ApplePhone은 이를 상속받아 필요한 기능만 추가하면 된다! 이렇게 각 출력문만 바꿔주고 슈퍼 클래스에서 받아올 수 있게 했다.


이렇게 잘 출력이 된다!

자체 채점

고려해보시면 좋을 기준

  1. 클래스 간 상/하위 관계(일반 클래스, 추상 클래스, 인터페이스 중 1개)를 활용합니다.
  2. 오버라이드를 적절히 활용하면 좋겠죠?
  3. 메소드 이름이 명확하면 좋겠습니다! (메소드명을 읽었을 때, 코드를 이해하는 데 모호하지 않다)
  4. Readme에 자신이 구현한 코드와 클래스를 설계한 이유를 설명합니다. (자유 형식)

내 생각대로 채점을 해보자!

  1. 일반 클래스와 추상 클래스, 인터페이스를 적절하게 사용해서 클래스의 상/하위 관계를 정의했다.
  2. 오버라이드를 통해 인터페이스에서 틀을 잡아둔 메서드명을 사용해 재정의했다.
  3. 메서드의 이름이 직관적이고 코드를 이해하는데 도움이 되는 것 같다. 사실 추상클래스의 명명을 어떻게 해야할까 고민했는데 추상 클래스의 명명에는 일반적으로 해당 클래스가 추상적인 성격을 갖고 있음을 명확히 나타내는 이름을 사용하는 것이 좋다고 해서 그대로 사용하게 되었다.
  4. 리드미를 추가할 예정이다!

0개의 댓글