Skip to content

Latest commit

Β 

History

History
480 lines (377 loc) Β· 18.5 KB

File metadata and controls

480 lines (377 loc) Β· 18.5 KB

Interface vs Abstract Class

상속 (Inheritance)

  • 상속 = μž¬μ‚¬μš© + ν™•μž₯
  • 상속은 λΆ€λͺ¨ν΄λž˜μŠ€(μƒμœ„ν΄λž˜μŠ€)λ‘œλΆ€ν„° μžμ‹ν΄λž˜μŠ€(ν•˜μœ„ν΄λž˜μŠ€)κ°€ 상속받아 λΆ€λͺ¨ν΄λž˜μŠ€μ˜ 멀버λ₯Ό κ·ΈλŒ€λ‘œ μ“Έ 수 μžˆκ²Œν•˜λŠ” 것
  • 객체지ν–₯의 상속은 κΈ°μ‘΄ 상속에 더해 거기에 ν•„μš”ν•œ νŠΉμ„±μ„ μΆ”κ°€, 즉 ν™•μž₯의 μ˜λ―Έκ°€ 강함 (μž¬μ‚¬μš© + ν™•μž₯)
  • μ‹œμž‘ν•˜κΈ° 전에 상속에 λŒ€ν•œ OverrdingλŠ” ν•΄λ‹Ή 정리 νŽ˜μ΄μ§€μ— μ •λ¦¬ν•΄λ‘μ—ˆμŒ

Abstract Class

  • 클래슀λ₯Ό 섀계도에 λΉ„μœ ν•˜λ©΄ 좔상 ν΄λž˜μŠ€λŠ” λ―Έμ™„μ„± μ„€κ³„λ„λ‘œ ν΄λž˜μŠ€μ— ν‚€μ›Œλ“œμΈ abstractλ₯Ό 뢙이면 됨
  • 좔상 ν΄λž˜μŠ€λŠ” 좔상 λ©”μ†Œλ“œλ₯Ό 0개 이상 κ°€μ§€κ³  μžˆλŠ” 클래슀둜 κ·Έ μ™Έμ—λŠ” 일반 ν΄λž˜μŠ€μ™€ λ‹€λ₯΄μ§€ μ•ŠμŒ
  • 좔상 ν΄λž˜μŠ€λŠ” 기본적으둜 일반 ν΄λž˜μŠ€μ™€ λΉ„μŠ·ν•˜λ―€λ‘œ ν•˜μœ„ ν΄λž˜μŠ€λ“€μ—κ²Œ 상속을 톡해 μ‚¬μš©ν•  수 μžˆκ²Œν•˜κ³  extends λΌλŠ” ν‚€μ›Œλ“œλ‘œ μƒμ†λ°›μŒ
  • 좔상 클래슀λ₯Ό 상속받을 경우 일반 ν΄λž˜μŠ€μ™€ λ‹€λ₯Έμ μ€ 좔상 λ©”μ†Œλ“œλΏμΈλ° ν•΄λ‹Ή 좔상 λ©”μ†Œλ“œλŠ” κ΅¬ν˜„μ΄ λ˜μ–΄μžˆμ§€ μ•ŠκΈ°λ•Œλ¬Έμ— λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ€ 상속받아 κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆμ§€λ§Œ 좔상 λ©”μ„œλ“œλ“€μ€ μž¬μ •μ˜(μ˜€λ²„λΌμ΄λ”©) ν•΄μ£Όμ–΄μ•Ό 함
  • 좔상 ν΄λž˜μŠ€λŠ” 즉, μž¬μ •μ˜ ν•΄μ£Όμ–΄μ•Όν•˜λ―€λ‘œ 객체λ₯Ό λ§Œλ“€ 수 μ—†λŠ” 클래슀이고 좔상 λ©”μ†Œλ“œλŠ” ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ λ©”μ†Œλ“œμ˜ κ΅¬ν˜„μ„ κ°•μ œν•¨
  • 좔상 클래슀λ₯Ό μƒμ†ν•˜λŠ” μ§‘ν•œκ°„μ—λŠ” 연관간계가 있고, λΉ„μŠ·ν•œ νŠΉμ§•μ„ κ°€μ§€κ³  μžˆλŠ” ν΄λž˜μŠ€λ“€μ—κ²Œ μ‚¬μš©ν•˜λŠ” νŠΉμ§•μ„ 가짐 -> μžμ‹ μ˜ κΈ°λŠ₯듀을 ν•˜μœ„ 클래슀둜 ν™•μž₯, 상속
  • 일반 ν΄λž˜μŠ€μ™€ λ™μΌν•˜κ²Œ extendsλ₯Ό μ‚¬μš©ν•˜μ—¬ 닀쀑 상속이 λΆˆκ°€λŠ₯
  • μƒμ†μ˜ κ΄€κ³„λŠ” is a (kind of) 관계라고 함
    • ex) Person is a Object

Interface

  • μΈν„°νŽ˜μ΄μŠ€λŠ” κ΅¬ν˜„λœ 것이 μ—†λŠ” λ°‘κ·Έλ¦Όλ§Œ κ·Έλ €μ Έ μžˆλŠ” κΈ°λ³Έ 섀계도
  • μΈν„°νŽ˜μ΄μŠ€λŠ” λͺ¨λ“  λ©”μ†Œλ“œκ°€ 좔상 λ©”μ†Œλ“œλ‘œ κ΅¬μ„±λ˜μ–΄ 있음. κ·ΈλŸ¬λ‚˜ 좔상 ν΄λž˜μŠ€μ—μ„œ 좔상 λ©”μ†Œλ“œμ™€ λ‹€λ₯΄κ²Œ public abstractλ₯Ό μƒλž΅ κ°€λŠ₯(무쑰건 λͺ¨λ“  λ©”μ†Œλ“œλŠ” public abstract)
  • μƒμ†μœΌλ‘œλŠ” inplements λΌλŠ” ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 상속받고 닀쀑상속이 κ°€λŠ₯
  • μƒμ†ν•˜λŠ” μ§‘ν•œκ°„μ—λŠ” 연관관계가 μ‘΄μž¬ν•˜μ§€ μ•Šμ„ 수 있음 -> μ •μ˜λœ λ©”μ†Œλ“œλ₯Ό 각 클래슀의 λͺ©μ μ— 맞게 κΈ°λŠ₯을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ ν™•μž₯, 상속
  • Java 8 λΆ€ν„° static, default λ©”μ†Œλ“œ μ‚¬μš©, 9 μ΄ν›„μ—λŠ” μΈν„°νŽ˜μ΄μŠ€ λ‚΄λΆ€μ—λ§Œ μ‚¬μš©ν•˜λŠ” private μ ‘κ·Όμ œν•œμž 이 κ°€λŠ₯해짐
  • μƒμ†μ˜ κ΄€κ³„λŠ” has a (kind of) 관계라고 함
    • ex) Person has a Swimming

invalid abstract method


Interface vs Abstract Class


μ‚¬μš© ꡬ뢄

  • μΈν„°νŽ˜μ΄μŠ€μ™€ 좔상 클래슀 λͺ¨λ‘ λ‹€ν˜•μ„±μ΄λ‚˜ 클래슀 νƒ€μž…μ„ ν†΅ν•©ν•œλ‹€λŠ” κΈ°λŠ₯은 λ™μΌν•˜μ§€λ§Œ μ‚¬μš©ν•˜λŠ” μœ„μΉ˜κ°€ λ‹€λ₯Ό 수 μžˆλ‹€
  • κ³΅ν†΅μœΌλ‘œ κ°€μ§€λŠ” λ©”μ†Œλ“œκ°€ λ§Žμ•„ 쀑볡 멀버 톡합을 μœ„ν•΄ κΈ°μ‘΄ 클래슀처럼 상속을 μ‚¬μš©ν•˜μ—¬ κ°€μ Έμ˜€λŠ”λ° ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ“œν•˜μ—¬ μž¬μ •μ˜ν•˜λŠ” κΈ°λŠ₯듀을 κ³΅μœ ν•˜κΈ° μœ„ν•œ 상속 κ°œλ…μ„ μ‚¬μš©ν•  λ•Œ 주둜 μ‚¬μš©ν•˜κ³  μΈν„°νŽ˜μ΄μŠ€μ™€ 달리 κΈ°μ‘΄ 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμ²˜λŸΌ μ œμ•½μ΄ μ—†μŒ
  • μΈν„°νŽ˜μ΄μŠ€λŠ” λŒ€μ‹  단 ν•˜λ‚˜λ§Œ 상속할 수 μžˆλŠ” κΈ°μ‘΄ ν΄λž˜μŠ€μ™€ λ‹€λ₯΄κ²Œ μ—¬λŸ¬ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속이 κ°€λŠ₯ν•˜κ³  μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ κΈ°λŠ₯을 μ •μ˜ν•˜λ˜ κ΅¬ν˜„ λ°©μ‹μ΄λ‚˜ λŒ€μƒμ— λŒ€ν•΄ μΆ”μƒν™”ν•˜λŠ”λ° μ‚¬μš©ν•  수 있음. ν΄λž˜μŠ€μ™€ λ‹€λ₯΄κ²Œ κ΅¬ν˜„ 객체가 같은 λ™μž‘μ„ ν•œλ‹€λŠ” 것을 보μž₯ν•˜κΈ° μœ„ν•΄ μ‚¬μš©

Interface default method

  • jdk 8 이후 interfaceμ—μ„œ κ΅¬ν˜„λΆ€κ°€ μžˆλŠ” 일반 λ©”μ„œλ“œλ₯Ό 생성이 κ°€λŠ₯
  • λ©”μ„œλ“œ 선언뢀에 default modifier μΆ”κ°€ ν›„ λ©”μ„œλ“œ κ΅¬ν˜„λΆ€ μž‘μ„±
    • μ ‘κ·Ό μ œν•œμžλŠ” public으둜 ν•œμ •λ¨ (μƒλž΅κ°€λŠ₯)
  • 기쑴에 interface 기반으둜 λ™μž‘ν•˜λŠ” 라이브러리의 interface에 μΆ”κ°€ν•΄μ•Ό ν•˜λŠ” κΈ°λŠ₯이 λ°œμƒν•˜μ—¬ ν•„μš”ν•˜κ²Œ λ˜μ—ˆμŒ
    • ν•΄λ‹Ή λ©”μ„œλ“œλŠ” abstractκ°€ μ•„λ‹ˆλ―€λ‘œ λ°˜λ“œμ‹œ κ΅¬ν˜„ν•΄μ•Ό ν•  ν•„μš”λŠ” μ—†μŒ
  • default λ©”μ„œλ“œμ˜ 좩돌의 경우 μš°μ„ μˆœμœ„λŠ” λ‹€μŒκ³Ό κ°™μŒ
    • super class method μš°μ„  : super classκ°€ ꡬ체적인 λ©”μ„œλ“œλ₯Ό κ°–λŠ” 경우 default λ©”μ„œλ“œλŠ” λ¬΄μ‹œλ¨
    • interface κ°„μ˜ 좩돌 : ν•˜λ‚˜μ˜ interfaceμ—μ„œ default λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜κ³  λ‹€λ₯Έ interfaceμ—μ„œλ„ 같은 μ΄λ¦„μ˜ λ©”μ„œλ“œκ°€ μžˆμ„ λ•Œ sub classλŠ” λ°˜λ“œμ‹œ override ν•΄μ„œ 좩돌 ν•΄κ²°

Interface static method

  • jdk 8 이후 interfaceμ—μ„œ κ΅¬ν˜„λΆ€κ°€ μžˆλŠ” static λ©”μ„œλ“œλ₯Ό 생성이 κ°€λŠ₯
  • 일반 static λ©”μ„œλ“œμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ λ³„λ„μ˜ 객체가 ν•„μš” μ—†μŒ
  • κ΅¬ν˜„μ²΄ 클래슀 없이 λ°”λ‘œ μΈν„°νŽ˜μ΄μŠ€ μ΄λ¦„μœΌλ‘œ λ©”μ„œλ“œμ— μ ‘κ·Όν•΄μ„œ μ‚¬μš©κ°€λŠ₯

Interface private method

  • jdk 9 이후 interfaceμ—μ„œ λ‚΄λΆ€μ μœΌλ‘œλ§Œ μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ private μ ‘κ·Όμ œν•œμž 생성이 κ°€λŠ₯. static ν‚€μ›Œλ“œλ‘œ μ‚¬μš©μ€ κ°€λŠ₯ν•˜μ§€λ§Œ defaultλŠ” μ‚¬μš©ν•˜μ§€ λͺ»ν•¨
    • 외뢀에 μ‚¬μš©ν•˜μ§€ λͺ»ν•˜κ²Œν•˜λŠ” private와 μ™ΈλΆ€μ—μ„œ μ‚¬μš©ν•˜κ²Œ ν•˜κΈ°μœ„ν•œ default μ‚¬μš© μ΄μœ κ°€ μƒλ°˜λ¨
  • μ™ΈλΆ€λ‘œ κ³΅κ°œν•  ν•„μš”κ°€ μ—†λŠ” λ©”μ„œλ“œ 지정을 μœ„ν•΄ private method μΆ”κ°€

interface MyInterface {
    default void defaultMethod() {
        helperMethod();
    }

    private void helperMethod() {
        System.out.println("Helper method in MyInterface");
    }

    static void staticMethod() {
        System.out.println("Static method in MyInterface");
    }

    private static void privateStaticHelperMethod() {
        System.out.println("Private static helper method in MyInterface");
    }
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = new MyInterface() {};
        myInterface.defaultMethod();
        MyInterface.staticMethod();
    }
}

Interface vs Abstract Class?

  • 즉 μœ„μ˜ 그림처럼 μΆ”μƒν΄λž˜μŠ€λŠ” λΆ€λͺ¨μ™€ μžμ‹κ°„μ— 연관관계가 μžˆλŠ” 상속이 ν•„μš”ν•˜μ§€λ§Œ νŠΉμ • κΈ°λŠ₯λ§Œμ„ μž¬μ •μ˜ ν•΄μ•Όν•  λ•Œ μ‚¬μš©
    • 동물-포유λ₯˜, 동물-μ‘°λ₯˜, 포유λ₯˜-고래, 포유λ₯˜-λ°•μ₯, μ‘°λ₯˜-μ°Έμƒˆ, μ‘°λ₯˜-νŽ­κ·„
  • μΈν„°νŽ˜μ΄μŠ€λŠ” μœ„μ²˜λŸΌ μ—°κ΄€κ΄€κ³„λŠ” μ—†μ§€λ§Œ νŠΉμ • κΈ°λŠ₯을 μΆ”μƒν™”ν•˜μ—¬ λ‚˜νƒ€λ‚΄μ•Ό ν•  경우 μ‚¬μš©. μ΄λŸ¬ν•œ κΈ°λŠ₯듀을 담은 μΈν„°νŽ˜μ΄μŠ€λŠ” 닀쀑 상속이 κ°€λŠ₯ν•˜λ―€λ‘œ ν‘œν˜„ν•˜κ³  싢은 κΈ°λŠ₯듀을 λ‹€μˆ˜ 상속받아 μž¬μ •μ˜ν•˜μ—¬ λ‚˜νƒ€λ‚΄λŠ” 것이 κ°€λŠ₯함
    • λ‚ μˆ˜μžˆλŠ”-λ°•μ₯, λ‚ μˆ˜μžˆλŠ”-μ°Έμƒˆ, ν—€μ—„μΉ μˆ˜μžˆλŠ”-고래, ν—€μ—„μΉ μˆ˜μžˆλŠ”-νŽ­κ·„
  • 연관관계에 차이도 μžˆμ§€λ§Œ λ‚˜λˆ μ„œ μ‚¬μš©ν•˜λŠ” κ°€μž₯ 큰 차이점은 μ‚¬μš© μš©λ„
    • μΆ”μƒν΄λž˜μŠ€μ˜ μ‚¬μš© μ˜λ„ : IS -A "~이닀"
    • μΈν„°νŽ˜μ΄μŠ€μ˜ μ‚¬μš© μ˜λ„ : HAS -A "~을 ν• μˆ˜μžˆλŠ”"
  • λͺ¨λ“  κΈ°λŠ₯듀을 μΈν„°νŽ˜μ΄μŠ€λ‘œ μ‚¬μš©ν•΄μ•Ό 되면 κΈ°μ‘΄ 상속을 톡해 λΆ€λͺ¨ν΄λž˜μŠ€μ—μ„œ 좔상 λ©”μ„œλ“œκ°€ μ•„λ‹Œ λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ„ κ·ΈλŒ€λ‘œ κ°€μ Έμ˜€λŠ” 것이 λΆˆκ°€λŠ₯ -> κ³΅ν†΅μœΌλ‘œ ν•„μš”ν•œ κΈ°λŠ₯도 μž¬μ •μ˜ν•΄μ•Όν•˜λŠ” λ²ˆκ±°λ‘œμ›€ 쑴재
abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

interface Swimmable {
    void swimming();
}

interface Flyable {
    void flying();
}

interface Talkable {
    void talking();
}

class Tiger extends Animal { }
class Parrot extends Animal { }
class People extends Animal implements Swimmable, Talkable{ // μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•¨μœΌλ‘œμ¨ λ™μž‘μ΄ ν•„μš”ν•œ ν΄λž˜μŠ€μ—λ§Œ λ”°λ‘œ 상속에 κ΅¬μ• λ°›μ§€μ•Šκ³  묢음
    @Override
    public void swimming() {}
}

class Whale extends Fish implements Swimmable{ 
    @Override
    public void swimming() {}
}

interface 좔상화λ₯Ό μΌλΆ€λ§Œ 가져와야 ν•˜λŠ” 경우

  • abstract classλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή νŠΉμ • λ©”μ„œλ“œλ§Œ μ‚¬μš©ν•˜λ„λ‘ ν•  수 있음
  • 좔상 클래슀λ₯Ό 상속받을 λ•Œ, κ·Έ 좔상 ν΄λž˜μŠ€κ°€ 이미 κ΅¬ν˜„ν•œ μΈν„°νŽ˜μ΄μŠ€μ˜ λ©”μ„œλ“œλŠ” ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ λ°˜λ“œμ‹œ κ΅¬ν˜„ν•  ν•„μš”λŠ” μ—†μ§€λ§Œ 좔상 ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„λ˜μ§€ μ•Šμ€ 좔상 λ©”μ„œλ“œλŠ” ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ λ°˜λ“œμ‹œ κ΅¬ν˜„ν•΄μ•Ό 함
interface InterfaceA {
    void methodA();
    void methodB();
}

interface InterfaceB {
    void methodC();
}

abstract class AbstractClass implements InterfaceA {
    @Override
    public void methodA() {
        System.out.println("Implemented methodA in AbstractClass");
    }
    // methodBλŠ” 좔상 λ©”μ„œλ“œλ‘œ 남겨두어 ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ΅¬ν˜„ν•˜λ„λ‘ 함
}

// ꡬ체적인 클래슀 μ •μ˜: 좔상 클래슀 상속
class ConcreteClass extends AbstractClass implements InterfaceB {
    @Override
    public void methodB() {
        System.out.println("Implemented methodB in ConcreteClass");
    }

    @Override
    public void methodC() {
        System.out.println("Implemented methodC in ConcreteClass");
    }
}

// ν…ŒμŠ€νŠΈ μ½”λ“œ
public class TestCode {
    public static void main(String[] args) {
        ConcreteClass concrete = new ConcreteClass();
        concrete.methodA(); // 좜λ ₯: Implemented methodA in AbstractClass
        concrete.methodB(); // 좜λ ₯: Implemented methodB in ConcreteClass
        concrete.methodC(); // 좜λ ₯: Implemented methodC in ConcreteClass
    }
}

μ‚¬μš© 비ꡐ

비ꡐ 좔상 클래슀 μΈν„°νŽ˜μ΄μŠ€
μ‚¬μš© ν‚€μ›Œλ“œ abstract interface
μ‚¬μš© κ°€λŠ₯ λ³€μˆ˜ μ œν•œ μ—†μŒ static, final, (μƒμˆ˜)
μ‚¬μš© κ°€λŠ₯ μ ‘κ·Ό μ œμ–΄μž μ œν•œ μ—†μŒ public
μ‚¬μš© κ°€λŠ₯ λ©”μ„œλ“œ μ œν•œ μ—†μŒ abstract method, default method, static method, private method
상속 ν‚€μ›Œλ“œ extends implements
닀쀑 상속 κ°€λŠ₯ μ—¬λΆ€ λΆˆκ°€λŠ₯ κ°€λŠ₯

둜또 κ΅¬ν˜„ 쀑 μ‚¬μš©μ„ ν•˜λ €λ˜ 이유

  • Lotto 객체와 WinningLotto 객체의 μœ νš¨μ„± 검사 방식은 λ™μΌν–ˆκ³  λ‹€λ₯Έ μœ νš¨μ„± 검사 방식이 μžˆμ–΄ νŠΉμ • 클래슀λ₯Ό 상속 λ°›λ˜ λ³΄λ„ˆμŠ€ λ²ˆν˜ΈκΉŒμ§€ μžˆλŠ” WinningLotto의 쀑볡 μœ νš¨μ„± 검사λ₯Ό μΆ”μƒν™”ν•˜λ € ν•˜μ˜€μŒ
    • κ·ΈλŸ¬λ‚˜ νŒŒλΌλ―Έν„°κ°€ 달라 μΆ”μƒν™”λ‘œ μ‚¬μš©ν•˜μ§€ λͺ»ν•˜μ˜€μŒ
    • 고민을 ν•΄λ΄€λŠ”λ° λ§Œμ•½ μ§„ν–‰ν–ˆλ‹€λ©΄ λ‹€μŒκ³Ό 같이 μ“°μ§€ μ•Šμ•˜μ„κΉŒ μ‹ΆμŒ
// Lotto 객체
public class Lotto extends ValidateLottoNumbers {
    private final static int NUMBERS_SIZE = 6;
    private final List<Integer> numbers;

    public Lotto(List<Integer> numbers) {
        validateSize(numbers, ErrorMessage.INVALID_LOTTO_SIZE);
        validateRange(numbers, ErrorMessage.INVALID_NUMBER_RANGE);
        validateDuplication(numbers);
    }

    @Override
    public void validateDuplication(List<Integer> numbers) {
        Set<Integer> notDuplicationNumbers = new HashSet<>(numbers);

        if (notDuplicationNumbers.size() != NUMBERS_SIZE) {
            throw new CustomIllegalArgumentException(ExceptionMessage.DUPLICATE_LOTTO_NUMBER);
        }
    }
}

// WinningLotto
public class WinningLotto extends ValidateLottoNumbers {
    private final static int WINNING_NUMBERS_SIZE = 7;
    private final List<Integer> numbers;
    private final int bonusNumber;

    public WinningLotto(List<Integer> numbers, int bonusNumber) {
        validateSize(numbers, ErrorMessage.INVALID_WINNING_NUMBERS_SIZE);
        validateRange(numbers, ErrorMessage.INVALID_WINNING_NUMBERS_RANGE);

        var validateNumbers = numbers.add(bonusNumber);
        validateDuplication(validateNumbers);
        validateBonusNumberRange(bonusNumber);
    }

    @Override
    public void validateDuplication(List<Integer> numbers) {
        Set<Integer> notDuplicationNumbers = new HashSet<>(numbers);
        notDuplicationNumbers.add(bonusNumber);

        if (notDuplicationNumbers.size() != WINNING_NUMBERS_SIZE) {
            throw new CustomIllegalArgumentException(ExceptionMessage.DUPLICATE_WINNING_NUMBER);
        }
    }

    private void validateBonusNumberRange(int bonusNumber) {
        if (bonusNumber < 1 || bonusNumber > 45) {
            throw new CustomIllegalArgumentException(ExceptionMessage.INVALID_BONUS_NUMBER_RANGE);
        }
    }
}

public abstract class ValidateLottoNumbers {
        private final static int NUMBERS_SIZE = 6;

    // ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” λ™μž‘μ΄ λ™μΌν•˜λ―€λ‘œ μƒμ†ν•˜μ—¬ 직접 μ‚¬μš©
    private void validateSize(List<Integer> numbers, ExceptionMessage exceptionMessage) {
        if (numbers.size() != NUMBERS_SIZE) {
            throw new CustomIllegalArgumentException(exceptionMessage);
        }
    }

    // // ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” λ™μž‘μ΄ λ™μΌν•˜λ―€λ‘œ μƒμ†ν•˜μ—¬ 직접 μ‚¬μš©
    private void validateRange(List<Integer> numbers, ExceptionMessage exceptionMessage) {
        for (int number : numbers) {
            if (validateNumberRange(number)) {
                throw new CustomIllegalArgumentException(exceptionMessage);
            }
        }
    }    

    public abstract void validateDuplication(List<Integer> numbers);
  • λ§Œμ•½ 객체 λ‚΄μ—μ„œ 직접 κ΅¬ν˜„ν•˜λ„λ‘ μ •μ˜ν•˜μ—¬ κ°•μ œν•˜λ € ν–ˆλ‹€λ©΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ‹€μŒκ³Ό 같이 μ‚¬μš©ν–ˆμ„ 것 κ°™μŒ
    • 섀계도 같은 λŠλ‚ŒμœΌλ‘œ μ‚¬μš©
    • μΈν„°νŽ˜μ΄μŠ€μ˜ μΆ”μƒλ©”μ„œλ“œλŠ” μ ‘κ·Όμ œν•œμžλ₯Ό λͺ¨λ‘ public으둜 μ‚¬μš©ν•΄μ•Όν•˜λ―€λ‘œ 상속받아 μ‚¬μš©ν•  경우 무쑰건 public으둜 μ‚¬μš©ν•˜μ—¬μ•Ό 함
  • java 8μ΄ν›„μ—λŠ” default ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜€λ²„λΌμ΄λ“œν•˜μ§€ μ•Šκ³  상속받아 μ‚¬μš©ν•  수 있음 ( μž¬μ •μ˜λ„ κ°€λŠ₯ν•˜μ§€λ§Œ μž¬μ •μ˜ ν•˜μ§€ μ•ŠμœΌλ©΄ ν•΄λ‹Ή λ©”μ„œλ“œκ°€ μ‚¬μš©λ¨ )
public interface ValidateLottoNumbers {
    public void validateSize(List<Integer> numbers);
    public void validateRange(List<Integer> numbers);
    public void validateDuplication(List<Integer> numbers);

    public default void testDefaultCode() {
        System.out.println("test");
    }
}

// Lotto 객체
public class Lotto implements ValidateLottoNumbers {
    public Lotto(List<Integer> numbers) {
        validateSize(numbers);
        validateRange(numbers);
        validateDuplication(numbers);

        // default λ©”μ„œλ“œλŠ” κ΅¬ν˜„μ—†μ΄ μ‚¬μš©κ°€λŠ₯
        testDefaultCode();
    }

    // 상속받은 κ°μ²΄λ§ˆλ‹€ λ‹€λ₯΄κ²Œ 둜직 κ΅¬ν˜„μ΄ κ°€λŠ₯ (상속받은 λ©”μ„œλ“œλŠ” λͺ¨λ‘ μΆ”μƒλ©”μ„œλ“œλ‘œ κ°•μ œ)
    @Override
    public void validateSize(List<Integer> numbers) {
        ...
    }

    @Override
    public void validateRange(List<Integer> numbers) {
        ...
    }

    @Override
    public void validateDuplication(List<Integer> numbers) {
        ...
    }
}

// WinningLotto
public class WinningLotto implements ValidateLottoNumbers {
    public WinningLotto(List<Integer> numbers, int bonusNumber) {
        validateSize(numbers);
        validateRange(numbers);
        var validateNumbers = numbers.add(bonusNumber);
        validateDuplication(validateNumbers);
        validateBonusNumberRange(bonusNumber);

        // default λ©”μ„œλ“œλŠ” μΆ”μƒν™”λœ 것이 μ•„λ‹ˆλ―€λ‘œ μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ 무방
    }

    // 상속받은 κ°μ²΄λ§ˆλ‹€ λ‹€λ₯΄κ²Œ 둜직 κ΅¬ν˜„μ΄ κ°€λŠ₯ (상속받은 λ©”μ„œλ“œλŠ” λͺ¨λ‘ μΆ”μƒλ©”μ„œλ“œλ‘œ κ°•μ œ)
    @Override
    public void validateSize(List<Integer> numbers) {
        ...
    }

    @Override
    public void validateRange(List<Integer> numbers) {
        ...
    }

    @Override
    public void validateDuplication(List<Integer> numbers) {
        ...
    }

    // μΆ”μƒλ˜μ§€ μ•Šμ€ 객체 λ‚΄λΆ€ λ©”μ„œλ“œ
    private void validateBonusNumberRange(int bonusNumber) {
        ...
    }
}

Ssafy Wizards CS Study

μΈν„°νŽ˜μ΄μŠ€μ™€ 좔상 클래슀의 차이

  • μ™œ ν΄λž˜μŠ€λŠ” 단일 μƒμ†λ§Œ κ°€λŠ₯ν•œλ°, μΈν„°νŽ˜μ΄μŠ€λŠ” 2개 이상 κ΅¬ν˜„μ΄ κ°€λŠ₯ν• κΉŒμš”?
μ •λ‹΅

μ™œ ν΄λž˜μŠ€λŠ” 단일 μƒμ†λ§Œ κ°€λŠ₯ν•œλ°, μΈν„°νŽ˜μ΄μŠ€λŠ” 2개 이상 κ΅¬ν˜„μ΄ κ°€λŠ₯ν• κΉŒμš”?

  • λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜(좔상화)만 μ •μ˜ν•˜κΈ° λ•Œλ¬Έμ— λ©”μ„œλ“œ κ΅¬ν˜„μ€ μž‘μ„±ν•˜μ§€ μ•Šμ•„ λ©”μ„œλ“œμ˜ 좩돌이 λ°œμƒν•˜μ§€ μ•ŠμŒ
    • κ΅¬ν˜„μ˜ μ±…μž„μ΄ ν΄λž˜μŠ€μ—κ²Œ 있음
  • λ””ν΄νŠΈ λ©”μ„œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμ§€λ§Œ μžλ°” μ»΄νŒŒμΌλŸ¬κ°€ λ””ν΄νŠΈ λ©”μ„œλ“œ 좩돌 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ 컴파일 νƒ€μž„μ— 검사λ₯Ό μˆ˜ν–‰ν•˜μ—¬ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚€λ―€λ‘œ 좩돌 문제λ₯Ό ν•΄κ²°ν•˜κ²Œ 함
public class Person1{
   void run() {		
   	    System.out.println("slow run");
   }
}

public class Person2{
   void run() {		
   	    System.out.println("fast run");
   }
}
// ν•΄λ‹Ή 클래슀λ₯Ό λ‘κ°œ 상속이 κ°€λŠ₯ν–ˆλ‹€λ©΄ μžμ‹ ν΄λž˜μŠ€λŠ” μ–΄λ–€ λΆ€λͺ¨μ˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Όν•˜λŠ”μ§€ νŒŒμ•…ν•  수 μ—†μŒ

public interface Person1{
   void run();
}

public interface Person2{
   void run();
}

public class Person3 implements Person1, Person2 {
    @Override
    void run() {
        System.out.println("상속 κ°€λŠ₯");
    }
}
// 단일 상속, 닀쀑 상속 λͺ¨λ‘ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속받은 ν΄λž˜μŠ€λŠ” λ©”μ„œλ“œλ₯Ό 직접 κ΅¬ν˜„ν•˜λ―€λ‘œ λ¬Έμ œκ°€ μΌμ–΄λ‚˜μ§€ μ•ŠμŒ -> λˆ„κ΅¬ν•œν…Œ 상속받은 건지 μ•Œ ν•„μš”κ°€ μ—†μŒ

μΆ”κ°€ : 같은 default λ©”μ„œλ“œλ₯Ό κ°€μ§„ 2개의 μΈν„°νŽ˜μ΄μŠ€ 상속 μ‹œ

  • 좩돌이 λ°œμƒν•˜λ©° μ»΄νŒŒμΌλŸ¬μ—μ„œ 였λ₯˜ λ°œμƒ
  • μΆ©λŒμ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ 직접 λͺ…μ‹œμ μœΌλ‘œ Ovveride μ‚¬μš©ν•˜κ±°λ‚˜ νŠΉμ • 클래슀λ₯Ό 지정해야함
public interface Student {

    String getName();

    default String getGreetingMessage() {
        return "Hi! I am a student!";
    }
}

public interface Citizen {

    String getName();

    default String getGreetingMessage() {
        return "Hi! I am a Citizen!";
    }
}

public class Brad implements Citizen, Student{

    @Override
    public String getName() {
        return "Brad";
    }

// μ€‘λ³΅λœ default λ©”μ„œλ“œλ‘œ 컴파일 μ—λŸ¬ λ°œμƒ
// μ•„λž˜ μ½”λ“œ 처럼 λͺ…μ‹œμ μœΌλ‘œ μ˜€λ²„λΌμ΄λ”© ν˜Ήμ€ κ΅¬ν˜„ 클래슀 지정을 μ§„ν–‰ν•˜μ—¬ μΆ©λŒμ„ ν•΄κ²°ν•΄μ•Ό 함

    // @Override
    // public String getGreetingMessage() {
    //     return "Hi! I am Brad!";
    // }

    // @Override
    // public String getGreetingMessage() {
    //     return Student.super.getGreetingMessage();
    // }
}
}

이후 μŠ€ν„°λ””λ₯Ό ν†΅ν•œ μ‚¬μš©ν•˜λŠ” 상황 비ꡐ λΈ”λ‘œκ·Έ


23-11-09

Reference