πŸ“‚ JAVA/μ£Όμš” κ°œλ…

좔상 클래슀(Abstract Class)

Amenable 2023. 6. 11. 18:40

πŸ“™ 1. μΆ”μƒν΄λž˜μŠ€λž€?

public abstract class Player {
    abstract void play();
    abstract void stop();
}

  클래슀λ₯Ό 섀계도라고 ν•œλ‹€λ©΄, μΆ”μƒν΄λž˜μŠ€(Abstract Class)λŠ” λ―Έμ™„μ„± 섀계도라고 ν•  수 μžˆλ‹€. μ—¬κΈ°μ„œ λ§ν•˜λŠ” 미완성은 단지 λ―Έμ™„μ„± λ©”μ„œλ“œ(좔상 λ©”μ„œλ“œ)λ₯Ό ν¬ν•¨ν•˜κ³  μžˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€. λ―Έμ™„μ„± μ„€κ³„λ„λ‘œ μ™„μ„±λœ μ œν’ˆμ„ λ§Œλ“€ 수 없듯이 좔상 클래슀둜 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λ‹€. 좔상 ν΄λž˜μŠ€λŠ” 상속을 ν†΅ν•΄μ„œ μžμ†ν΄λž˜μŠ€μ— μ˜ν•΄μ„œλ§Œ 완성될 수 μžˆλ‹€.

 

  좔상 클래슀 μžμ²΄λ‘œλŠ” ν΄λž˜μŠ€λ‘œμ„œμ˜ 역할을 λ‹€ λͺ»ν•˜μ§€λ§Œ, μƒˆλ‘œμš΄ 클래슀λ₯Ό μž‘μ„±ν•˜λŠ” 데 μžˆμ–΄μ„œ 바탕이 λ˜λŠ” 쑰상 ν΄λž˜μŠ€λ‘œμ„œ μ€‘μš”ν•œ 의미λ₯Ό κ°–λŠ”λ‹€. 좔상 ν΄λž˜μŠ€λŠ” ν΄λž˜μŠ€μ— 좔상화λ₯Ό μ ‘λͺ©μ‹œμΌœ 보닀 ꡬ쑰적이게 객체λ₯Ό μ„€κ³„ν•˜κ³ , ν”„λ‘œκ·Έλž¨μ˜ μœ μ§€λ³΄μˆ˜μ„±μ„ 올렀주며, 만일 ν”„λ‘œκ·Έλž¨μ— μ–΄λ– ν•œ κΈ°λŠ₯을 μ—…κ·Έλ ˆμ΄λ“œν•œλ‹€κ³  ν•˜λ©΄ μˆ˜μ •κ³Ό 좔가에 λŒ€ν•΄ μœ μ—°μ μ΄κ²Œ ν•˜μ—¬, 퀄리티 높은 ν”„λ‘œκ·Έλž¨κ³Ό μ†”λ£¨μ…˜μ„ κ°œλ°œν•  수 있게 ν•΄μ€€λ‹€.

 

  참고둜 좔상 λ©”μ„œλ“œλ₯Ό ν¬ν•¨ν•˜κ³  μžˆμ§€ μ•Šμ€ ν΄λž˜μŠ€μ—λ„ ν‚€μ›Œλ“œ 'abstract'λ₯Ό λΆ™μ—¬μ„œ 좔상 클래슀둜 μ§€μ •ν•  μˆ˜λ„ μžˆλ‹€. 좔상 λ©”μ„œλ“œκ°€ μ—†λŠ” μ™„μ„±λœ 클래슀라 할지라도 μΆ”μƒν΄λž˜μŠ€λ‘œ μ§€μ •λ˜λ©΄ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λ‹€.

 

 

πŸ“™ 2. 좔상 λ©”μ„œλ“œ

  좔상 ν΄λž˜μŠ€λž€ 좔상 λ©”μ„œλ“œλ₯Ό 일반적으둜 ν¬ν•¨ν•˜κ³  μžˆλŠ”λ°, 좔상 λ©”μ„œλ“œμ— λŒ€ν•΄μ„œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜μž. λ©”μ„œλ“œλŠ” 선언뢀와 κ΅¬ν˜„λΆ€(λͺΈν†΅)둜 κ΅¬μ„±λ˜μ–΄ μžˆλ‹€. μ„ μ–ΈλΆ€λ§Œ μž‘μ„±ν•˜κ³  κ΅¬ν˜„λΆ€λŠ” μž‘μ„±ν•˜μ§€ μ•Šμ€ μ±„λ‘œ λ‚¨κ²¨ λ‘” κ²ƒμ΄ μΆ”μƒλ©”μ„œλ“œλ‹€.

public abstract class Player {
    abstract void play(); // 좔상 λ©”μ„œλ“œ
    abstract void stop(); // 좔상 λ©”μ„œλ“œ
}

  즉, μ„€κ³„λ§Œ ν•΄ 놓고 μ‹€μ œ μˆ˜ν–‰λ  λ‚΄μš©μ€ μž‘μ„±ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— λ―Έμ™„μ„± λ©”μ„œλ“œμΈ 것이닀. μ‹€μ œ μž‘μ—…λ‚΄μš©μΈ κ΅¬ν˜„λΆ€κ°€ μ—†λŠ” λ©”μ„œλ“œκ°€ 무슨 μ˜λ―Έκ°€ μžˆμ„κΉŒ 싢기도 ν•˜κ² μ§€λ§Œ, λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  λ•Œ μ‹€μ œ μž‘μ—…λ‚΄μš©μΈ κ΅¬ν˜„λΆ€λ³΄λ‹€ 더 μ€‘μš”ν•œ 뢀뢄이 선언뢀이닀.

  λ©”μ„œλ“œμ˜ 이름과 λ©”μ„œλ“œμ˜ μž‘μ—…μ— ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜, 그리고 μž‘μ—…μ˜ 결과둜 μ–΄λ–€ νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•  것인가λ₯Ό κ²°μ •ν•˜λŠ” 것은 쉽지 μ•Šμ€ 일이닀. κ·Έλž˜μ„œ μ„ μ–ΈλΆ€λ§Œ μž‘μ„±ν•΄λ„ λ©”μ„œλ“œμ˜ 절반 이상이 μ™„μ„±λœ 것이라 해도 과언이 μ•„λ‹ˆλ‹€.

 

 

πŸ“™ 3. μΆ”μƒν΄λž˜μŠ€ μ‚¬μš©λ²•

  μΆ”μƒν΄λž˜μŠ€λŠ” μ•„λž˜μ™€ 같이 abstractλ₯Ό μ΄μš©ν•˜μ—¬ μž‘μ„±ν•  수 μžˆλ‹€.

public abstract class Player {
    abstract void play();
    abstract void stop();
}

  그리고 μΆ”μƒν΄λž˜μŠ€λ‘œλΆ€ν„° μƒμ†λ°›λŠ” μžμ†ν΄λž˜μŠ€κ°€ μ˜€λ²„λΌμ΄λ”©μ„ 톡해 쑰상인 μΆ”μƒν΄λž˜μŠ€μ˜ 좔상 λ©”μ„œλ“œλ₯Ό λͺ¨λ‘ κ΅¬ν˜„ν•¨μœΌλ‘œμ¨ μΆ”μƒν΄λž˜μŠ€μ˜ μ‚¬μš©μ΄ κ°€λŠ₯ν•΄μ§„λ‹€. 

public class AudioPlayer extends Player {

    @Override
    void play() {
        System.out.println("AudioPlayer Play~");
    }

    @Override
    void stop() {
        System.out.println("AudioPlayer Stop!!");
    }
}

  만일 μ‘°μƒμœΌλ‘œλΆ€ν„° 상속받은 좔상 λ©”μ„œλ“œ 쀑 ν•˜λ‚˜λΌλ„ κ΅¬ν˜„ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄, μžμ†ν΄λž˜μŠ€ μ—­μ‹œ 좔상 클래슀둜 μ§€μ •ν•΄ μ£Όμ–΄μ•Ό ν•œλ‹€.

public abstract class CDPlayer extends Player{

    @Override
    void play() {
        System.out.println("CDPlayer Play~");
    }

    // 좔상 λ©”μ„œλ“œμΈ stop()을 κ΅¬ν˜„ν•˜μ§€ μ•ŠμŒ
}

 

 

πŸ“™ 4. μΆ”μƒν΄λž˜μŠ€μ˜ μƒμ„±μž

  μ•žμ—μ„œ 좔상 클래슀λ₯Ό μ΄μš©ν•˜μ—¬ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μ—†λ‹€κ³  μ–ΈκΈ‰ν•˜μ˜€λ‹€. 즉, 좔상 ν΄λž˜μŠ€λŠ” 클래슀의 일쒅이라고 ν•˜μ§€λ§Œ new μƒμ„±μžλ₯Ό 톡해 μΈμŠ€ν„΄μŠ€ 객체λ₯Ό 직접 λ§Œλ“€ 수 μ—†λ‹€. μ™œλƒν•˜λ©΄ μΆ”상 ν΄λž˜μŠ€λŠ” μƒμ† κ΅¬μ‘°μ—μ„œ λΆ€λͺ¨ ν΄λž˜μŠ€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” μ—­ν• λ‘œλ§Œ μ΄μš©λ˜κΈ° λ•Œλ¬Έμ΄λ‹€.

public abstract class Player {
    abstract void play();
    abstract void stop();

    public Player() {
        System.out.println("Player Constructor");
    }
}

public static void main(String[] args) {
    Player player = new Player(); // ERROR
}

  λ”°λΌμ„œ λ°˜λ“œμ‹œ 좔상 ν΄λž˜μŠ€λŠ” μ–΄λŠ μžμ‹μ˜ ν΄λž˜μŠ€μ— μƒμ†μ‹œν‚€κ³ , μžμ‹ 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•˜μ—¬ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

public abstract class Player {
    abstract void play();
    abstract void stop();

    public Player() {
        System.out.println("Player Constructor!!");
    }
}

public class AudioPlayer extends Player {

    @Override
    void play() {
        System.out.println("AudioPlayer Play~");
    }

    @Override
    void stop() {
        System.out.println("AudioPlayer Stop!!");
    }
}

public static void main(String[] args) {
    AudioPlayer audioPlayer = new AudioPlayer(); // Player Constructor!!
}

  μΈμŠ€ν„΄μŠ€λ₯Ό 직접 λ§Œλ“€ 수 없을 뿐, super() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ 좔상 클래슀의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€λŠ” 점을 μ•Œμ•„λ‘λ„λ‘ ν•˜μž.

 

 

πŸ“™ 5. μΆ”상 ν΄λž˜μŠ€μ˜ ν™œμš©

πŸ“Œ 1. 곡톡 λ©€λ²„μ˜ ν†΅ν•©μœΌλ‘œ 쀑볡 제거

  μ•„λž˜μ™€ 같이 AudioPlayer, CDPlayer λͺ¨λ‘ nameμ΄λΌλŠ” ν•„λ“œμ™€ play()와 stop()μ΄λΌλŠ” λ©”μ„œλ“œλ₯Ό κ°€μ§„λ‹€κ³  ν•˜μž.

public class AudioPlayer {

    String name;

    void play() {
        System.out.println("AudioPlayer Play~");
    }

    void stop() {
        System.out.println("AudioPlayer Stop!!");
    }
}

public abstract class CDPlayer{

    String name;

    void play() {
        System.out.println("CDPlayer Play~");
    }

    void stop() {
        System.out.println("CDPlayer Stop!!");
    }
}

  μ΄λŠ” 좔상 클래슀λ₯Ό μ΄μš©ν•˜μ—¬ 곡톡 멀버λ₯Ό ν†΅ν•©ν•˜κ³  쀑볡을 μ œκ±°ν•  수 μžˆλ‹€.

public abstract class Player {

    String name;
    abstract void play();
    abstract void stop();
}

public class AudioPlayer extends Player {

    @Override
    void play() {
        System.out.println("AudioPlayer Play~");
    }

    @Override
    void stop() {
        System.out.println("AudioPlayer Stop!!");
    }
}

public abstract class CDPlayer extends Player {

    @Override
    void play() {
        System.out.println("CDPlayer Play~");
    }

    @Override
    void stop() {
        System.out.println("CDPlayer Stop!!");
    }
}

  이 뢀뢄이 μΆ”μƒν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€μ˜ 차이라고 ν•  수 μžˆλ‹€. Java8의 μΈν„°νŽ˜μ΄μŠ€λ„ μΆ”μƒν΄λž˜μŠ€μ™€ 같이 ν•„λ“œλ₯Ό μ„ μ–Έν•΄ 쀄 수 μžˆμ§€λ§Œ, λͺ¨λ“  λ©€λ²„λ³€μˆ˜λŠ” public static final이어야 ν•œλ‹€λŠ” μ œμ•½μ‚¬ν•­μ΄ μžˆλ‹€. 즉, 곡톡 μƒμˆ˜κ°€ λ˜μ–΄ λ²„λ¦°λ‹€λŠ” 것이닀.

  ν•˜μ§€λ§Œ, 좔상 클래슀λ₯Ό μ΄μš©ν•œλ‹€λ©΄ μžμ‹ ν΄λž˜μŠ€μ—μ„œ μ€‘λ³΅λ˜λŠ” λ³€μˆ˜λ“€μ„ μƒμ†μœΌλ‘œ λ¬Άμ–΄ ν†΅ν•©μ‹œμΌœ μ£ΌλŠ” κΈ°λŠ₯을 μ œκ³΅ν•  수 μžˆλ‹€.

πŸ“Œ 2. κ΅¬ν˜„μ˜ κ°•μ œμ„±μ„ ν†΅ν•œ κΈ°λŠ₯ λ³΄μž₯

  abstractλ₯Ό λΆ™μ—¬μ„œ μΆ”μƒλ©”μ„œλ“œλ‘œ μ„ μ–Έν•˜λŠ” μ΄μœ λŠ” μžμ† ν΄λž˜μŠ€μ—μ„œ 좔상 λ©”μ„œλ“œλ₯Ό λ°˜λ“œμ‹œ κ΅¬ν˜„ν•˜λ„λ‘ κ°•μš”ν•˜κΈ° μœ„ν•΄μ„œλ‹€
Animalμ΄λΌλŠ” μΆ”μƒν΄λž˜μŠ€κ°€ μžˆκ³  μ΄κ²ƒμ„ μžμ†ν΄λž˜μŠ€κ°€ μƒμ†ν•œλ‹€κ³  κ°€μ •ν•΄ 보자.

public abstract class Animal {

    abstract void eat();
}

public class Dog extends Animal {
    
    @Override
    void eat() {
        System.out.println("Dog is eating!!");
    }
}

public class Cat extends Animal {

    @Override
    void eat() {
        System.out.println("Cat is eating!!");
    }
}

public static void main(String[] args) {
    Animal[] animals = {new Dog(), new Cat()};

    for(Animal animal : animals){
        animal.eat();
    }
}

// 좜λ ₯
Dog is eating!!
Cat is eating!!

  여기에 Catμ΄λΌλŠ” μƒˆλ‘œμš΄ 동물이 μΆ”κ°€λ˜μ—ˆλ‹€κ³  생각해 보자. 만읡 Cat ν΄λž˜μŠ€κ°€ eat()μ΄λΌλŠ” 좔상 λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šμ•˜κ³ , 그리고 이것이 λ¬Έμ œκ°€ λ˜μ§€ μ•ŠλŠ”λ‹€λΌκ³  ν•˜λ©΄ λ‹€μŒ μ½”λ“œμ—μ„œ λŸ°νƒ€μž„ μƒν™©μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•  것이닀.

public class Lion extends Animal{
}

public static void main(String[] args) {
    Animal[] animals = {new Dog(), new Cat(), new Lion()};

    for(Animal animal : animals){
        animal.eat();
    }
}

  Lion은 eat()을 μ˜€λ²„λΌμ΄λ”© ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— animal λ°°μ—΄ μ•ˆμ— μžˆλŠ” Lion은 eat() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•  수 μ—†λ‹€.

  ν•˜μ§€λ§Œ, 좔상 ν΄λž˜μŠ€λŠ” κ΅¬ν˜„μ„ κ°•μ œν•˜κΈ° λ•Œλ¬Έμ— 컴파일 μ‹œμ μ— eat()을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ„ 것을 μ•Œ 수 μžˆμ–΄μ„œ μœ„μ™€ 같은 λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ ν•΄μ€€λ‹€.

πŸ“Œ 3. κ·œκ²©μ— λ§žλŠ” 섀계 κ΅¬ν˜„

  좔상 클래슀λ₯Ό μƒμ†ν•˜κ²Œ 되면 미리 κ·œκ²©μ— 맞게 μ„ μ–ΈλΆ€κ°€ μž‘μ„±λ˜μ–΄ 있기 λ•Œλ¬Έμ— μ„ μ–ΈλΆ€λ₯Ό κ³ λ―Όν•  ν•„μš” 없이 κ΅¬ν˜„λΆ€λ§Œ μž‘μ„±ν•˜μ—¬ κ·œκ²©μ— 맞게 섀계λ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

 

ν•΄λ‹Ή 글은
남ꢁ성 λ‹˜μ˜ 'μžλ°”μ˜ 정석',
Inpa λ‹˜μ˜ '좔상 클래슀(Abstract) μš©λ„ μ™„λ²½ μ΄ν•΄ν•˜κΈ°'
λ₯Ό μ°Έκ³ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.