Skip to content

Latest commit

ย 

History

History
667 lines (501 loc) ยท 29.3 KB

File metadata and controls

667 lines (501 loc) ยท 29.3 KB

item 20 : ์ถ”์ƒํด๋ž˜์Šค๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ณ ๋ คํ•˜๋ผ

1. ์ž๋ฐ”์—์„œ์˜ ๋‹ค์ค‘ ๊ตฌํ˜„ ๋งค์ปค๋‹ˆ์ฆ˜

{% hint style="info" %} ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‹ค์ค‘ ๊ตฌํ˜„ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค {% endhint %}

์ž๋ฐ”8๋ถ€ํ„ฐ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋„ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ๋˜์–ด ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค ๋ชจ๋‘ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‘˜์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ์ •์˜ํ•œ ํƒ€์ž…์„ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ž๋ฐ”๋Š” ๋‹จ์ผ ์ƒ์†๋งŒ ์ง€์›ํ•˜๋‹ˆ ํฐ ์ œ์•ฝ์ด๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์„ ์–ธํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ์ •์˜ํ•˜๊ณ  ๊ทธ ๊ทœ์•ฝ์„ ์ง€ํ‚จ ํด๋ž˜์Šค๋ผ๋ฉด ๋‹ค๋ฅธ ์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด๋„ ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค.

2. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์˜ ์žฅ์ 

1) ๊ธฐ์กด ํด๋ž˜์Šค์—๋„ ์†์‰ฝ๊ฒŒ ์ƒˆ๋กœ์šด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค

{% hint style="success" %} ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ (์•„์ง ์—†๋‹ค๋ฉด) ์ถ”๊ฐ€ํ•˜๊ณ , ํด๋ž˜์Šค ์„ ์–ธ์— implements ๊ตฌ๋ฌธ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋์ด๋‹ค. {% endhint %}

์ž๋ฐ” ํ”Œ๋žซํผ์—์„œ๋„ Comparable, Iterable, AutoCloseable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ƒˆ๋กœ ์ถ”๊ฐ€๋์„ ๋•Œ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ˆ˜๋งŽ์€ ๊ธฐ์กด ํด๋ž˜์Šค๊ฐ€ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ๊ตฌํ˜„ํ•œ ์ฑ„ ๋ฆด๋ฆฌ์Šค๋๋‹ค.

// ์ƒˆ๋กœ์šด ์ธํ„ฐํŽ˜์ด์Šค Comparable ์ถ”๊ฐ€
// Employee ํด๋ž˜์Šค๋Š” Person์„ ์ƒ์†ํ•˜๋ฉด์„œ Comparable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค
interface Comparable<T> {
    int compareTo(T o);
}

// ๊ธฐ์กด ํด๋ž˜์Šค
class Person {
    private String name;

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

    public String getName() {
        return name;
    }
}

// Person ํด๋ž˜์Šค๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค Comparable์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
class Employee extends Person implements Comparable<Employee> {
    private int id;

    public Employee(String name, int id) {
        super(name);
        this.id = id;
    }

    @Override
    public int compareTo(Employee o) {
        return Integer.compare(this.id, o.id); // Employee์˜ id๋กœ ๋น„๊ต
    }
}

public class Main {
    public static void main(String[] args) {
        Employee e1 = new Employee("Alice", 100);
        Employee e2 = new Employee("Bob", 200);

        System.out.println(e1.compareTo(e2)); // -1 ์ถœ๋ ฅ
    }
}

๋ฐ˜๋ฉด ๊ธฐ์กด ํด๋ž˜์Šค ์œ„์— ์ƒˆ๋กœ์šด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋ผ์›Œ๋„ฃ๊ธฐ๋Š” ์–ด๋ ค์šด ๊ฒŒ ์ผ๋ฐ˜์ ์ด๋‹ค. ๋‘ ํด๋ž˜์Šค๊ฐ€ ๊ฐ™์€ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด, ๊ทธ ์ถ”์ƒ ํด๋ž˜์Šค๋Š” ๊ณ„์ธต๊ตฌ์กฐ์ƒ ๋‘ ํด๋ž˜์Šค์˜ ๊ณตํ†ต ์กฐ์ƒ์ด์–ด์•ผ ํ•œ๋‹ค. ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ์ž์†์ด ์ด๋ฅผ ์ƒ์†ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ๋„ ๊ฐ•์ œ๋กœ ๋ง์ด๋‹ค.

// ์ƒˆ๋กœ์šด ์ถ”์ƒ ํด๋ž˜์Šค ์ถ”๊ฐ€
abstract class Animal {
    public abstract void makeSound();
}

// ๊ธฐ์กด ํด๋ž˜์Šค
class Dog {
    public void bark() {
        System.out.println("๋ฉ๋ฉ");
    }
}

// ๊ธฐ์กด ํด๋ž˜์Šค
class Cat {
    public void meow() {
        System.out.println("์•ผ์˜น");
    }
}

// ์ƒˆ๋กœ์šด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ ์šฉํ•˜๊ธฐ ์–ด๋ ค์šด ์ƒํ™ฉ
// Dog๊ณผ Cat์€ Animal์„ ์ƒ์†ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•จ

class AnimalDog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("๋ฉ๋ฉ");
    }
}

class AnimalCat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("์•ผ์˜น");
    }
}

public class Main {
    public static void main(String[] args) {
        AnimalDog dog = new AnimalDog();
        AnimalCat cat = new AnimalCat();

        dog.makeSound(); // ๋ฉ๋ฉ ์ถœ๋ ฅ
        cat.makeSound(); // ์•ผ์˜น ์ถœ๋ ฅ
    }
}

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋˜๋ฉด, ๊ณ„์ธต ๊ตฌ์กฐ๊ฐ€ ๊ฐ•์ œ๋กœ ๋ณ€๊ฒฝ๋˜๋ฉฐ, ๊ธฐ์กด ์„ค๊ณ„์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ๋ถˆํ•„์š”ํ•œ ์ƒ์†์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

2) ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฏน์Šค์ธ(mixin) ์ •์˜์— ์•ˆ์„ฑ๋งž์ถค์ด๋‹ค.

{% hint style="info" %} ๋ฏน์Šค์ธ์ด๋ž€ ํด๋ž˜์Šค๊ฐ€ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์œผ๋กœ, ๋ฏน์Šค์ธ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์— ์›๋ž˜์˜ ์ฃผ๋œ ๊ธฐ๋Šฅ์™ธ์— ๋„ ํŠน์ • ์„ ํƒ์  ๊ธฐ๋Šฅ์„ ๋”ํ•˜๋Š” ํšจ {% endhint %}

์ด ์—ญํ• ์„ ๋ณดํ†ต ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, ์ถ”์ƒ ํด๋ž˜์Šค๋กœ๋Š” ๋ฏน์Šค์ธ์„ ์ •์˜ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋‚ด์šฉ์€ ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ž๋ฐ”์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๐Ÿง ๋ฏน์Šค์ธ(Mixin)์ด๋ž€?

๋ฏน์Šค์ธ์€ ํ•˜๋‚˜์˜ ์ฃผ๋œ ํด๋ž˜์Šค์— ์„ ํƒ์ ์ธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ, ์—ฌ๋Ÿฌ ํด๋ž˜์Šค์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Comparable ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์–ด๋–ค ํด๋ž˜์Šค๋“  ์ƒ๊ด€์—†์ด, ๊ทธ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋“ค ์‚ฌ์ด์— ๋น„๊ต ๊ธฐ๋Šฅ์„ ๋”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

๐Ÿง ์™œ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋ฏน์Šค์ธ์„ ์ •์˜ํ•  ์ˆ˜ ์—†์„๊นŒ?

์ž๋ฐ”๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ํด๋ž˜์Šค๊ฐ€ ์ด๋ฏธ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ์œผ๋ฉด ์ถ”๊ฐ€์ ์œผ๋กœ ๋‹ค๋ฅธ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ๋ฏน์Šค์ธ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ถ”์ƒ ํด๋ž˜์Šค๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฏน์Šค์ธ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ์™€ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค ํ•  ๋•Œ์˜ ๋ฌธ์ œ์ 

1. ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฏน์Šค์ธ ๊ตฌํ˜„ (๊ฐ€๋Šฅ)

// Comparable ์ธํ„ฐํŽ˜์ด์Šค๋Š” '๋ฏน์Šค์ธ' ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
interface Comparable<T> {
    int compareTo(T o);
}

// ์ฃผ๋œ ํด๋ž˜์Šค: Person
class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

// Person ํด๋ž˜์Šค์— ๋ฏน์Šค์ธ ์ธํ„ฐํŽ˜์ด์Šค(Comparable)๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
class Employee extends Person implements Comparable<Employee> {
    private int id;

    public Employee(String name, int age, int id) {
        super(name, age);
        this.id = id;
    }

    @Override
    public int compareTo(Employee o) {
        return Integer.compare(this.id, o.id); // Employee์˜ id๋กœ ๋น„๊ต
    }

    public int getId() {
        return id;
    }
}

public class Main {
    public static void main(String[] args) {
        Employee emp1 = new Employee("Alice", 30, 101);
        Employee emp2 = new Employee("Bob", 25, 102);

        System.out.println(emp1.compareTo(emp2)); // -1 ์ถœ๋ ฅ
    }
}

์„ค๋ช…:

  • Person ํด๋ž˜์Šค๊ฐ€ Employee๋กœ ํ™•์žฅ๋˜์—ˆ๊ณ , ์ถ”๊ฐ€์ ์œผ๋กœ Comparable<Employee>๋ผ๋Š” ๋ฏน์Šค์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด Employee ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋“ค๋ผ๋ฆฌ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋ฏน์Šค์ธ ์ •์˜ (๋ถˆ๊ฐ€๋Šฅ)

// ์ถ”์ƒ ํด๋ž˜์Šค ์ •์˜
abstract class ComparableMixin {
    public abstract int compare(Object o);
}

// ์ด๋ฏธ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋Š” ์ฃผ๋œ ํด๋ž˜์Šค
class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

// ์ž๋ฐ”๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, Person ํด๋ž˜์Šค๊ฐ€ ComparableMixin์„ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์—†๋‹ค.
class Employee extends Person /*, ComparableMixin */ {
    private int id;

    public Employee(String name, int age, int id) {
        super(name, age);
        this.id = id;
    }

    // compare ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ ๋‹ค์ค‘ ์ƒ์† ๋ถˆ๊ฐ€๋กœ ์ถ”์ƒ ํด๋ž˜์Šค ์ ์šฉ ๋ถˆ๊ฐ€
    /*
    @Override
    public int compare(Object o) {
        Employee emp = (Employee) o;
        return Integer.compare(this.id, emp.id);
    }
    */
}
  • Employee ํด๋ž˜์Šค๋Š” ์ด๋ฏธ Person ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ComparableMixin์ด๋ผ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์—†๋‹ค.
  • ์ž๋ฐ”๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ด ์ƒํ™ฉ์—์„œ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋ฏน์Šค์ธ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํด๋ž˜์Šค์˜ ์ฃผ๋œ ๊ธฐ๋Šฅ ์™ธ์— ์„ ํƒ์  ๊ธฐ๋Šฅ์„ ๋ฏน์Šค์ธ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•˜๋‹ค. ์ฆ‰, Comparable๊ณผ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํด๋ž˜์Šค์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฐ˜๋ฉด, ์ถ”์ƒ ํด๋ž˜์Šค๋Š” ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์ œํ•œํ•˜๋ฏ€๋กœ, ์ƒˆ๋กœ์šด ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋„์ž…ํ•˜์—ฌ ๋ฏน์Šค์ธ ์—ญํ• ์„ ํ•˜๋ ค๋ฉด ์ƒ์† ์ œ์•ฝ์— ๊ฑธ๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ž๋ฐ”๊ฐ€ ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

3) ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋Š” ๊ณ„์ธต๊ตฌ์กฐ๊ฐ€ ์—†๋Š” ํƒ€์ž… ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

{% hint style="success" %} ํƒ€์ž… ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ๋•Œ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ณ„์ธต์˜ ์ œ์•ฝ ์—†์ด ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์–ด ์œ ์—ฐํ•˜๋‹ค. {% endhint %}

๋ฐ˜๋ฉด, ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ผํ•œ ํƒ€์ž…์„ ์ •์˜ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์กฐํ•ฉ์˜ ์ˆ˜๊ฐ€ ๊ธ‰๊ฒฉํžˆ ๋Š˜์–ด๋‚˜๋ฉด์„œ ๋ณต์žกํ•ด์ง€๋Š” ๋ฌธ์ œ(์กฐํ•ฉ ํญ๋ฐœ)๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  1. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ์—ฐ์„ฑ:
    • ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์ค‘ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ€์ˆ˜(Singer)์™€ ์ž‘๊ณก๊ฐ€(Songwriter)๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ๊ฐ ์ •์˜ํ•˜๊ณ , ๊ฐ€์ˆ˜์ด๋ฉด์„œ ์ž‘๊ณก๊ฐ€์ธ ์‚ฌ๋žŒ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
    • ๋” ๋‚˜์•„๊ฐ€, Singer์™€ Songwriter๋ฅผ ํ™•์žฅํ•˜๊ณ  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ œ3์˜ ์ธํ„ฐํŽ˜์ด์Šค(SingerSongwriter)๋ฅผ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
// ๊ฐ€์ˆ˜ ์ธํ„ฐํŽ˜์ด์Šค
public interface Singer {
    AudioClip sing(Song s);  // ๊ฐ€์ˆ˜๋Š” ๋…ธ๋ž˜๋ฅผ ๋ถ€๋ฆ„
}

// ์ž‘๊ณก๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค
public interface Songwriter {
    Song compose(int chartPosition);  // ์ž‘๊ณก๊ฐ€๋Š” ๋…ธ๋ž˜๋ฅผ ๋งŒ๋“ฆ
}

// ๊ฐ€์ˆ˜์ด์ž ์ž‘๊ณก๊ฐ€์ธ ์ธํ„ฐํŽ˜์ด์Šค
public interface SingerSongwriter extends Singer, Songwriter {
    AudioClip strum();  // ์ถ”๊ฐ€ ๊ธฐ๋Šฅ: ์•…๊ธฐ๋ฅผ ์—ฐ์ฃผํ•  ์ˆ˜ ์žˆ์Œ
    void actSensitive();  // ์ถ”๊ฐ€ ๊ธฐ๋Šฅ: ๊ฐ์„ฑ์ ์ธ ํ–‰๋™์„ ํ•  ์ˆ˜ ์žˆ์Œ
}
  • Singer์™€ Songwriter ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ๊ฐ ๊ฐ€์ˆ˜์™€ ์ž‘๊ณก๊ฐ€์˜ ์—ญํ• ์„ ์ •์˜ํ•œ๋‹ค.
  • SingerSongwriter ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•˜์—ฌ ๊ฐ€์ˆ˜์ด๋ฉด์„œ ์ž‘๊ณก๊ฐ€์ธ ์‚ฌ๋žŒ์„ ํ‘œํ˜„ํ•œ๋‹ค. ๋˜ํ•œ, ์•…๊ธฐ ์—ฐ์ฃผ(strum())์™€ ๊ฐ์„ฑ์  ํ–‰๋™(actSensitive()) ๊ฐ™์€ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ๋„ ์ •์˜ํ•œ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ˆ˜์ด๋ฉด์„œ ์ž‘๊ณก๊ฐ€์ธ ๋™์‹œ์— ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ์˜ ์ œํ•œ:
  • ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„์Šทํ•œ ์กฐํ•ฉ์„ ๋งŒ๋“ค๋ฉด, ๋‹ค์ค‘ ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์ˆ˜์ด๋ฉด์„œ ์ž‘๊ณก๊ฐ€์ธ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด ๋ณ„๋„์˜ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
  • ์†์„ฑ์˜ ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก, ๋ชจ๋“  ์กฐํ•ฉ์„ ํด๋ž˜์Šค๋กœ ํ‘œํ˜„ํ•˜๋ ค๋ฉด ๊ทธ๋งŒํผ ๋งŽ์€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ด์„œ ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ๊ฐ€ ๋น„๋Œ€ํ•ด์ง€๋Š” ๋ฌธ์ œ(์กฐํ•ฉ ํญ๋ฐœ)๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

2. ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ์˜ ๋ฌธ์ œ์ 

// ๊ฐ€์ˆ˜ ํด๋ž˜์Šค
class SingerClass {
    public AudioClip sing(Song s) {
        // ๊ฐ€์ˆ˜์˜ ๋…ธ๋ž˜ ๋ถ€๋ฅด๊ธฐ ๊ธฐ๋Šฅ
    }
}

// ์ž‘๊ณก๊ฐ€ ํด๋ž˜์Šค
class SongwriterClass {
    public Song compose(int chartPosition) {
        // ์ž‘๊ณก๊ฐ€์˜ ์ž‘๊ณก ๊ธฐ๋Šฅ
    }
}

// ๊ฐ€์ˆ˜์ด์ž ์ž‘๊ณก๊ฐ€์ธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋‹ค์ค‘ ์ƒ์†์ด ์•ˆ๋˜๋ฏ€๋กœ ๋ถˆํŽธํ•จ์ด ๋ฐœ์ƒ
class SingerSongwriterClass extends SingerClass {
    // ์ž‘๊ณก๊ฐ€ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์ถ”๊ฐ€ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•จ
    public Song compose(int chartPosition) {
        // ์ž‘๊ณก๊ฐ€์˜ ์ž‘๊ณก ๊ธฐ๋Šฅ ์ถ”๊ฐ€
    }

    // ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
    public AudioClip strum() {
        // ์•…๊ธฐ ์—ฐ์ฃผ ๊ธฐ๋Šฅ
    }

    public void actSensitive() {
        // ๊ฐ์„ฑ์  ํ–‰๋™ ๊ธฐ๋Šฅ
    }
}

์„ค๋ช…:

  • SingerClass์™€ SongwriterClass๋ฅผ ํด๋ž˜์Šค๋กœ ์ •์˜ํ•˜๋ ค๋ฉด, ๋‹ค์ค‘ ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์— ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ง์ ‘ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ€์ˆ˜์ด์ž ์ž‘๊ณก๊ฐ€์ธ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋ ค๋ฉด, SingerClass๋ฅผ ์ƒ์†ํ•˜๊ณ  ๋ณ„๋„๋กœ SongwriterClass์˜ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
  • ํด๋ž˜์Šค๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๊ฐ ์กฐํ•ฉ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์กฐํ•ฉ์ด ๋งŽ์•„์ง€๋ฉด ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์ง€๊ณ  ๋ณต์žกํ•ด์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

{% hint style="info" %} ์ฆ‰, ์ธํ„ฐํŽ˜์ด์Šค์˜ ์žฅ์ ์€

  • ๋‹ค์ค‘ ์ƒ์† ๊ฐ€๋Šฅ: ์ž๋ฐ”์—์„œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋™์‹œ์— ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์œ ์—ฐ์„ฑ: ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์ด ๋†’์•„์ง€๊ณ , ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‚ฎ์€ ๊ฒฐํ•ฉ๋„: ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง„๋‹ค. {% endhint %}

4) ๋ž˜ํผ ํด๋ž˜์Šค ๊ด€์šฉ๊ตฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ธฐ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์•ˆ์ „ํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์ˆ˜๋‹จ์ด ๋œ๋‹ค.

ํƒ€์ž…์„ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์ •์˜ํ•ด๋‘๋ฉด ๊ทธ ํƒ€์ž…์— ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ์†๋ฟ์ด๋‹ค. ์ƒ์†ํ•ด์„œ ๋งŒ๋“  ํด๋ž˜์Šค๋Š” ๋ž˜ํผ ํด๋ž˜์Šค๋ณด๋‹ค ํ™œ์šฉ๋„๊ฐ€ ๋–จ์–ด์ง€๊ณ  ๊นจ์ง€๊ธฐ ์‰ฝ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ ์ค‘ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์ด ๋ช…๋ฐฑํ•œ ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด, ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋Š” ์ œ์•ฝ์ด ์žˆ๋‹ค.

  • equals์™€ hashcode๋ฅผ ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋กœ ์ œ๊ณต ์•ˆํ•จ
  • ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๊ณ , private ์ •์  ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค.
  • ๋ณธ์ธ์ด ๋งŒ๋“  ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹ˆ๋ฉด ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ

๊ทธ๋ฆฌ๊ณ  ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ๋•Œ๋Š” ์ƒ์†ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•œ ์„ค๋ช…์„ @implSpec ์ž๋ฐ”๋… ํƒœ๊ทธ๋ฅผ ๋ถ™์—ฌ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•œ๋‹ค.

3. ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค

{% hint style="success" %} ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š” ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๊ตฌํ˜„ํ•ด๋‘๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๋กœ, ์ด๋ฅผ ํ™•์žฅํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. {% endhint %}

1) ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ, ๊ณจ๊ฒฉ ๊ตฌํ˜„์— ๋Œ€ํ•œ ์„ค๋ช…

  1. ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค:
    • ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์ค‘ ๊ตฌํ˜„์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. ํด๋ž˜์Šค๋Š” ๋‹ค์ค‘ ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋™์‹œ์— ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•˜๋‹ค.
    • ์ถ”์ƒ ํด๋ž˜์Šค๋Š” ๋‹จ์ผ ์ƒ์†๋งŒ ํ—ˆ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ์— ์ œํ•œ์ด ์žˆ๋‹ค. ๋˜ํ•œ, ํ•œ ๋ฒˆ ์ƒ์†๋˜๋ฉด ๋‹ค๋ฅธ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ํ•จ๊ป˜ ์ƒ์†ํ•  ์ˆ˜ ์—†์–ด์„œ ํ™•์žฅ์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.
  2. ๋””ํดํŠธ ๋ฉ”์„œ๋“œ

{% hint style="info" %} ๋ชฉ์ : ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ผ๋ถ€ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์—ฌ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ๊ตฌํ˜„ํ•  ๋•Œ, ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•  ํ•„์š”๋ฅผ ์—†์• ์ค€๋‹ค. {% endhint %}

  • ๋„์ž… ์‹œ๊ธฐ: ์ž๋ฐ” 8

  • ํ•˜์ง€๋งŒ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ equals, hashCode, toString ๊ฐ™์€ Object ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ๋“ค์€ ์—ฌ์ „ํžˆ ์ถ”์ƒ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

  • ์‚ฌ์šฉ ์˜ˆ:

    public interface MyInterface {
        // ์ถ”์ƒ ๋ฉ”์„œ๋“œ
        void abstractMethod();
    
        // ๋””ํดํŠธ ๋ฉ”์„œ๋“œ
        default void defaultMethod() {
            System.out.println("This is a default method.");
        }
    }
  • ์ฃผ์š” ์žฅ์ 

    • ๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋‹ค์ค‘ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜์—ฌ, ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
    • ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ์œ ์ง€ํ•œ ์ฑ„ ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ๋ณด์žฅํ•˜๋ฉด์„œ๋„ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ๊ณจ๊ฒฉ ๊ตฌํ˜„(Skeletal Implementation)

{% hint style="info" %} ๋ชฉ์ : ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ผ๋ถ€ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์—ฌ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ๊ตฌํ˜„ํ•  ๋•Œ, ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•  ํ•„์š”๋ฅผ ์—†์• ์ค€๋‹ค. {% endhint %}

  • ๋„์ž… ์‹œ๊ธฐ: ์ž๋ฐ” 1.2 (์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ)
  • ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š” ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋งŽ์€ ๋ฉ”์„œ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๊ตฌํ˜„ํ•ด๋‘๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์ด๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ๋”ฐ๋ฅธ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„ ๋ถ€๋‹ด์ด ํฌ๊ฒŒ ์ค„์–ด๋“ ๋‹ค.
  • ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ œ๊ณตํ•˜๋Š” AbstractCollection, AbstractSet, AbstractList, AbstractMap ๋“ฑ์ด ๋Œ€ํ‘œ์ ์ธ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์˜ˆ
  1. ๊ณจ๊ฒฉ ๊ตฌํ˜„์˜ ์ œ์•ฝ ์‚ฌํ•ญ
  • ์ƒ์† ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ๋‹จ์ผ ์ƒ์†๋งŒ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํด๋ž˜์Šค๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋งŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์—, ํ•„๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ , protected๋‚˜ private ์ ‘๊ทผ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ๊ณจ๊ฒฉ ๊ตฌํ˜„์˜ ์žฅ์ 
  • ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์˜ AbstractList๋Š” List ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ณต์žกํ•œ ๋ฉ”์„œ๋“œ๋“ค(์˜ˆ: contains, isEmpty)์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜์—ฌ, ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.
  • ํ•„๋“œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๊ณ  ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์บก์Аํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • protected ๋ฉ”์„œ๋“œ๋‚˜ ํ•„๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค ์ž‘์„ฑ ๋ฐฉ๋ฒ•:
abstract class AbstractList<E> implements List<E> {
    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public boolean contains(Object o) {
        for (E e : this) {
            if (e.equals(o)) return true;
        }
        return false;
    }

    // ์ถ”๊ฐ€์ ์œผ๋กœ ๋” ๋งŽ์€ ๋ฉ”์„œ๋“œ๋ฅผ ๊ณจ๊ฒฉ ๊ตฌํ˜„์œผ๋กœ ์ œ๊ณต
}
  • ๋จผ์ € ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ถ„์„ํ•ด, ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์ •ํ•˜๊ณ , ์ด ๋ฉ”์„œ๋“œ๋“ค์€ ๊ณจ๊ฒฉ ๊ตฌํ˜„์—์„œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋กœ ๋‚จ๊ธด๋‹ค.
  • ๊ทธ๋‹ค์Œ, ๊ธฐ๋ฐ˜ ๋ฉ”์„œ๋“œ๋“ค๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•œ๋‹ค.
  • equals, hashCode, toString ๋“ฑ Object ๋ฉ”์„œ๋“œ๋Š” ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ์ถ”์ƒ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

2) ์˜ˆ์‹œ ์ฝ”๋“œ

1. ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ™œ์šฉํ•œ List ๊ตฌํ˜„

๋‹ค์Œ ์ฝ”๋“œ๋Š” int[] ๋ฐฐ์—ด์„ ๋ฐ›์•„ List<Integer> ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ

// ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•ด ์™„์„ฑํ•œ List ํด๋ž˜์Šค
static List<Integer> intArrayAsList(int[] a) {
    Objects.requireNonNull(a); // null ๊ฐ’ ๋ฐฉ์ง€

    return new AbstractList<>() {
        @Override
        public Integer get(int i) {
            return a[i]; // ์˜คํ† ๋ฐ•์‹ฑ
        }

        @Override
        public Integer set(int i, Integer val) {
            int oldVal = a[i];
            a[i] = val; // ์˜คํ† ์–ธ๋ฐ•์‹ฑ
            return oldVal; // ์˜คํ† ๋ฐ•์‹ฑ
        }

        @Override
        public int size() {
            return a.length;
        }
    };
}
  • ์„ค๋ช…: ์ด ์ฝ”๋“œ๋Š” int[] ๋ฐฐ์—ด์„ ๋ฐ›์•„ List<Integer> ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ1 ์—ญํ• ์„ ํ•œ๋‹ค. AbstractList๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋กœ, ์ด๋ฅผ ์ƒ์†๋ฐ›์•„ ํ•„์š”ํ•œ get(), set(), size() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฆฌ์ŠคํŠธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ž‘์—…์ด ํฌ๊ฒŒ ์ค„์–ด๋“ ๋‹ค.

2. ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์˜ˆ์‹œ (Map.Entry)

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ž๋ฐ”์˜ Map.Entry ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ„ํ•œ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค

public abstract class AbstractMapEntry<K,V> implements Map.Entry<K,V> {

    // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์—”ํŠธ๋ฆฌ๋Š” ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.
    @Override
    public V setValue(V value) {
        throw new UnsupportedOperationException(); // ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Œ
    }

    // equals ๋ฉ”์„œ๋“œ์˜ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ๊ตฌํ˜„ํ•œ๋‹ค.
    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof Map.Entry)) return false;
        Map.Entry<?,?> e = (Map.Entry<?,?>) o;
        return Objects.equals(e.getKey(), getKey()) &&
               Objects.equals(e.getValue(), getValue());
    }

    // hashCode ๋ฉ”์„œ๋“œ์˜ ์ผ๋ฐ˜ ๊ทœ์•ฝ์„ ๊ตฌํ˜„ํ•œ๋‹ค.
    @Override
    public int hashCode() {
        return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
    }

    // toString ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
    @Override
    public String toString() {
        return getKey() + "=" + getValue();
    }
}
  • ์„ค๋ช…: ์ด ํด๋ž˜์Šค๋Š” Map.Entry ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ณจ๊ฒฉ ๊ตฌํ˜„์ด๋‹ค. equals, hashCode, toString ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด๋‘์—ˆ์œผ๋ฉฐ, setValue()๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋„๋ก ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๊ฒŒ ๋˜์–ด ์žˆ๋‹ค. ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ด ๋ฉ”์„œ๋“œ๋“ค์„ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

3. ๋‹จ์ˆœ ๊ตฌํ˜„์˜ ์˜ˆ (AbstractMap.SimpleEntry)

๋‹จ์ˆœ ๊ตฌํ˜„์€ ๊ณจ๊ฒฉ ๊ตฌํ˜„๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ฉฐ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ˜„

public class SimpleEntry<K,V> implements Map.Entry<K,V> {
    private final K key;
    private V value;

    public SimpleEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public K getKey() {
        return key;
    }

    @Override
    public V getValue() {
        return value;
    }

    @Override
    public V setValue(V value) {
        V old = this.value;
        this.value = value;
        return old;
    }
}
  • ์„ค๋ช…: SimpleEntry๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š” ์•„๋‹ˆ์ง€๋งŒ, Map.Entry ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ํ•„์š”์— ๋”ฐ๋ผ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

{% hint style="success" %} ๋””ํดํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ถ”์ƒ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค(AbstractCharacter)๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์ค‘๋ณต์„ ์—†์•จ ์ˆ˜ ์žˆ๋‹ค. {% endhint %}

3) ๋””ํดํŠธ ๋ฉ”์„œ๋“œ์™€ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ๋น„๊ต

ํŠน์ง• ๋””ํดํŠธ ๋ฉ”์„œ๋“œ ๊ณจ๊ฒฉ ๊ตฌํ˜„ (Skeletal Implementation)
๊ตฌํ˜„ ์œ„์น˜ ์ธํ„ฐํŽ˜์ด์Šค ์•ˆ์—์„œ ์ œ๊ณต ์ถ”์ƒ ํด๋ž˜์Šค์—์„œ ์ œ๊ณต
์ƒ์† ๊ตฌ์กฐ ๋‹ค์ค‘ ์ƒ์† ๊ฐ€๋Šฅ (์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ ์ƒ์†) ๋‹จ์ผ ์ƒ์† (ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๊ณจ๊ฒฉ ๊ตฌํ˜„ ํด๋ž˜์Šค๋งŒ ์ƒ์† ๊ฐ€๋Šฅ)
ํ•„๋“œ ์‚ฌ์šฉ ์ธ์Šคํ„ด์Šค ํ•„๋“œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€ ์ธ์Šคํ„ด์Šค ํ•„๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
๋ฉ”์„œ๋“œ ์ œ๊ณต ๋ฒ”์œ„ ์ฃผ๋กœ ๊ฐ„๋‹จํ•œ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ (๊ตฌํ˜„ ์ฝ”๋“œ๊ฐ€ ์ ์Œ) ๋ณต์žกํ•œ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ ๊ฐ€๋Šฅ (๊ตฌํ˜„ ์ฝ”๋“œ๊ฐ€ ๋งŽ์„ ์ˆ˜ ์žˆ์Œ)
์ฃผ๋œ ํ™œ์šฉ ์ฃผ๋กœ ์ž‘์€ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๊ธฐ๋ณธ ๋™์ž‘ ์ œ๊ณต ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ณต์žกํ•œ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
Object ๋ฉ”์„œ๋“œ ์ œ์•ฝ equals, hashCode, toString์€ ๊ตฌํ˜„ ๋ถˆ๊ฐ€ equals, hashCode, toString์€ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
ํ•˜์œ„ ํ˜ธํ™˜์„ฑ ๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์œ ์šฉ ํด๋ž˜์Šค ํ™•์žฅ์„ ํ†ตํ•ด ์ƒ์†๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„

โœจ ์ตœ์ข… ์ •๋ฆฌ

{% hint style="success" %} ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์ค‘ ๊ตฌํ˜„์šฉ ํƒ€์ž…์œผ๋กœ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค. {% endhint %}

๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ผ ๋ฉด ๊ตฌํ˜„ํ•˜๋Š” ์ˆ˜๊ณ ๋ฅผ ๋œ์–ด์ฃผ๋Š” ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ํ•จ๊ป˜ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ผญ ๊ณ ๋ คํ•ด๋ณด์ž. ๊ณจ๊ฒฉ ๊ตฌํ˜„์€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•˜์—ฌ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๋ชจ๋“  ๊ณณ์—์„œ ํ™œ์šฉํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๊ฐ€๋Šฅํ•œ ํ•œ์ด๋ผ๊ณ  ํ•œ ์ด์œ ๋Š”, ์ธํ„ฐํŽ˜์ด์Šค์— ๊ฑธ๋ ค ์žˆ๋Š” ๊ตฌํ˜„์ƒ์˜ ์ œ์•ฝ ๋•Œ๋ฌธ์— ๊ณจ๊ฒฉ ๊ตฌํ˜„์„ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ํ”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฐธ๊ณ  ๊ธ€ : https://velog.io/@injoon2019/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C-%EC%9E%90%EB%B0%94-%EC%95%84%EC%9D%B4%ED%85%9C20.-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%B3%B4%EB%8B%A4%EB%8A%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EC%9A%B0%EC%84%A0%ED%95%98%EB%9D%BC

Footnotes

  1. ์–ด๋Œ‘ํ„ฐ(Adapter)๋Š” ์†Œํ”„ํŠธ์›จ์–ด ๋””์ž์ธ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜๋กœ, ์„œ๋กœ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค๋“ค์ด ํ•จ๊ป˜ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

    ์ด ํŒจํ„ด์€ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค๋“ค์ด ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ค‘๊ฐ„์—์„œ ๋ณ€ํ™˜ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ์ผ์ข…์˜ "๋ณ€ํ™˜๊ธฐ" ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ž๋ฐ”์—์„œ๋Š” ํŠนํžˆ ์ปฌ๋ ‰์…˜, ์ŠคํŠธ๋ฆผ, ๋ฐฐ์—ด ๋“ฑ์„ ๋ณ€ํ™˜ํ•  ๋•Œ ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์„ ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์˜ ์‚ฌ์šฉ ๋ชฉ์ :

    1. ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
    2. ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด, ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

    ์˜ˆ์‹œ๋กœ ์„ค๋ช…ํ•œ ์ฝ”๋“œ์—์„œ ์–ด๋Œ‘ํ„ฐ์˜ ์—ญํ• :

    static List<Integer> intArrayAsList(int[] a) {
        return new AbstractList<>() {
            @Override
            public Integer get(int i) {
                return a[i]; // int ๋ฐฐ์—ด์˜ ๊ฐ’์„ Integer๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ œ๊ณต
            }
    
            @Override
            public Integer set(int i, Integer val) {
                int oldVal = a[i];
                a[i] = val; // Integer ๊ฐ’์„ int ๋ฐฐ์—ด์— ์ €์žฅ
                return oldVal;
            }
    
            @Override
            public int size() {
                return a.length; // ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๋กœ ๋ฐ˜ํ™˜
            }
        };
    }
    

    ์ด ์ฝ”๋“œ๋Š” int[] ๋ฐฐ์—ด์„ ๋ฐ›์•„ **List<Integer>**๋กœ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค. ์ฆ‰, ๋ฐฐ์—ด์„ ๋ฆฌ์ŠคํŠธ์ฒ˜๋Ÿผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ๋ณ€ํ™˜ํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

    • int[] ๋ฐฐ์—ด์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์„ ์‚ฌ์šฉํ•˜๊ณ , **๋ฆฌ์ŠคํŠธ(List)**๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ๋‘ ๊ฐ€์ง€๋Š” ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋ฏ€๋กœ, ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์„ ํ†ตํ•ด ๋ฐฐ์—ด์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

    ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์˜ ์ผ๋ฐ˜์ ์ธ ๊ตฌ์กฐ:

    1. ํด๋ผ์ด์–ธํŠธ(Client): ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
    2. ์–ด๋Œ‘ํ‹ฐ(Adaptee): ๊ธฐ์กด ํด๋ž˜์Šค, ์ฆ‰ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๋Œ€์ƒ์ž…๋‹ˆ๋‹ค.
    3. ์–ด๋Œ‘ํ„ฐ(Adapter): ์–ด๋Œ‘ํ‹ฐ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

    ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์˜ ๊ฐ„๋‹จํ•œ ์˜ˆ:

    // ๊ธฐ์กด ํด๋ž˜์Šค
    class OldSystem {
        public void oldMethod() {
            System.out.println("Old method is called");
        }
    }
    
    // ์–ด๋Œ‘ํ„ฐ ์ธํ„ฐํŽ˜์ด์Šค
    interface NewSystem {
        void newMethod();
    }
    
    // ์–ด๋Œ‘ํ„ฐ ํด๋ž˜์Šค
    class Adapter implements NewSystem {
        private OldSystem oldSystem;
    
        public Adapter(OldSystem oldSystem) {
            this.oldSystem = oldSystem;
        }
    
        @Override
        public void newMethod() {
            oldSystem.oldMethod(); // ๊ธฐ์กด ๋ฉ”์„œ๋“œ๋ฅผ ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋กœ ๋ณ€ํ™˜
        }
    }
    
    // ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ
    public class Main {
        public static void main(String[] args) {
            OldSystem oldSystem = new OldSystem();
            NewSystem adapter = new Adapter(oldSystem);
            adapter.newMethod(); // ์–ด๋Œ‘ํ„ฐ๋ฅผ ํ†ตํ•ด oldMethod()๋ฅผ ํ˜ธ์ถœ
        }
    }
    

    ์œ„ ์˜ˆ์‹œ์—์„œ, OldSystem์€ ๊ธฐ์กด ์‹œ์Šคํ…œ์„ ํ‘œํ˜„ํ•˜๊ณ  Adapter๋Š” ์ด๋ฅผ NewSystem ์ธํ„ฐํŽ˜์ด์Šค์— ๋งž๊ฒŒ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด OldSystem์˜ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โ†ฉ