์ด์ ๊ธ์ ํตํด ์ธํฐํ์ด์ค์ ์ฅ์ ๋ค์ ์์๋ณด์๋ค.
์ด๋ฒ ๊ธ์์๋ ์ธํฐํ์ด์ค์ ๊ณจ๊ฒฉ ๊ตฌํ(skeletal implementation) ํด๋์ค๋ฅผ ํจ๊ป ์ ๊ณตํ์ฌ ์ธํฐํ์ด์ค์ ์ถ์ ํด๋์ค์ ์ฅ์ ์ ๋ชจ๋ ์ทจํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
์ธํฐํ์ด์ค์ ์ถ์ ํด๋์ค๋ฅผ ๊ฐ์ด ์ฌ์ฉํ์ ๋์ ์ฅ์ ์ '์ธํฐํ์ด์ค์์ ๊ตฌํํด ์ค ์ ์๋ ๊ฒ๋ค์ ๋ํดํธ ๋ฉ์๋๋ก ๊ตฌํํ๊ณ , ๊ตฌํํด ์ค ์ ์๋ ๊ฒ๋ค์ ์ถ์ ๊ณจ๊ฒฉ ํด๋์ค์์ ๋๋จธ์ง ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค.'๋ ๊ฒ์ด๋ค.
์ถ์ ๊ณจ๊ฒฉ ๊ตฌํ ํด๋์ค๋ฅผ ํ์ฉํ์์ ๋ ์ป์ ์ ์๋ 2๊ฐ์ง์ ์ฅ์ ์ ๋ํด์ ์์ธํ ์์๋ณด์.
(๋ช ์นญ๊ณผ ๊ด๋ จํ์ฌ, ์ถ์ ๊ณจ๊ฒฉ ํด๋์ค๋ผ๊ณ ๋ถ๋ฅด๋ ์ด์ ๋ ์ผ๋ถ๋ง ๊ตฌํํ๊ณ ์ผ๋ถ๋ ๊ตฌํํ์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ธํฐํ์ด์ค๊ฐ ๋ผ๋ ์ญํ ์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ์ฌ์ธ ๊ฑฐ ๊ฐ๋ค.)
์ฅ์ 1. ๋จ์ํ ๋จ์ ๊ณจ๊ฒฉ ๊ตฌํ์ ํ์ฅํ๋ ๊ฒ๋ง์ผ๋ก ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๋ฐ ํ์ํ ๋๋ถ๋ถ์ด ์๋ฃ๋๋ค. (=ํ ํ๋ฆฟ ๋ฉ์๋ ํจํด) ๐
๊ด๋ก์ ์ธํฐํ์ด์ค ์ด๋ฆ์ด Interfact๋ผ๋ฉด ๊ทธ ๊ณจ๊ฒฉ ๊ตฌํ ํด๋์ค์ ์ด๋ฆ์ AbstractInterface๋ก ์ง๋๋ค. ์ ๋๋ก ์ค๊ณํ๋ค๋ฉด ๊ณจ๊ฒฉ ๊ตฌํ์ (๋ ๋ฆฝ๋ ํฌ์ ํด๋์ค๋ ๋ํดํธ ๋ฉ์๋๋ก ์ด๋ฃจ์ด์ง ์ธํฐํ์ด์ค๋ ) ๊ทธ ์ธํฐํ์ด์ค๋ก ๋๋ฆ์ ๊ตฌํ์ ๋ง๋ค๋ ค๋ ํ๋ก๊ทธ๋๋จธ์ ์ผ์ ์๋นํ ๋์ด์ค๋ค.
์๋๋ ๊ณจ๊ฒฉ ๊ตฌํ์ ์ฌ์ฉํด ์์ฑํ ๊ตฌ์ฒด ํด๋์ค์ด๋ค.
static List<Integer> intArrayAsList(int[] a) {
Objects.requireNonNull(a);
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;
}
};
}
๋ง์ฝ ๊ณจ๊ฒฉ ๊ตฌํ์ ์ฌ์ฉํ์ง ์์๋ค๋ฉด ๋ฐํ๊ฐ์ธ List<Integer>๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ 'size(), isEmpty(), contains(Object o), iterator(),...' ๋ฑ ์๋ง์ ๋ฉ์๋๋ฅผ ์ง์ ๊ตฌํํด์ผ ํ๋ค.
ํ์ง๋ง AbstractList๋ผ๋ ๊ณจ๊ฒฉ ๊ตฌํ์ ์ด์ฉํ์ฌ 'get()'๊ณผ 'size()'๋ง ๊ตฌํํ๋ฉด ๋๊ณ , ์ถ๊ฐ์ ์ผ๋ก 'set()'๊ณผ ๊ฐ์ ์ฌ์ ์ํ๊ณ ์ถ์ ๊ฒ๋ค์ ์ค๋ฒ๋ผ์ด๋ํ ์ ์๋ค.
์ฅ์ 2. ์๋ฎฌ๋ ์ดํธํ ๋ค์ค ์์(simulated multiple inheritance)์ ์ฌ์ฉํ ์ ์๋ค. ๐
AbstractCat์ ์์๋ฐ๊ณ ์๋ MyCat ํด๋์ค๊ฐ ์๋ค๊ณ ํ์.
public abstract class AbstractCat {
protected abstract String sound();
protected abstract String name();
}
----------
public class MyCat extends AbstractCat implements Flyable{
@Override
protected String sound() {
return "์ผ์น";
}
@Override
protected String name() {
return "amenable";
}
}
----------
public static void main(String[] args) {
MyCat myCat = new MyCat();
System.out.println(myCat.sound()); // ์ผ์น
System.out.println(myCat.name()); // amenable
}
์ฌ๊ธฐ์ AbstractFlyable์ ์ถ๊ฐ์ ์ผ๋ก ์์๋ฐ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ํ ๊น? (๊ณจ๊ฒฉ ๊ตฌํ์ ํ์ฉํ์ฌ ์ป์ ์ ์๋ ์ด์ ์ผ๋ก ์ธํด์ ๊ณจ๊ฒฉ ๊ตฌํ์ ์์๋ฐ๊ณ ์ถ์ ๊ฒฝ์ฐ์ด๋ค.)
๊ณจ๊ฒฉ ๊ตฌํ ํด๋์ค๋ฅผ ์๋์ ๊ฐ์ด ์ฐํ์ ์ผ๋ก ์ด์ฉํ๋ค๋ฉด ๋ค์ค ์์๊ณผ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋๋ฆด ์ ์๋ค. ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค์์ ํด๋น ๊ณจ๊ฒฉ ๊ตฌํ์ ํ์ฅํ private ๋ด๋ถ ํด๋์ค๋ฅผ ์ ์ํ๋ค.
- ๊ฐ ๋ฉ์๋ ํธ์ถ์ ๋ด๋ถ ํด๋์ค์ ์ธ์คํด์ค์ ์ ๋ฌํ๋ค.
public interface Flyable {
void fly();
}
----------
public class AbstractFlyable implements Flyable {
@Override
public void fly() {
System.out.println("๋ ์๊ฐ๋ค~");
}
}
----------
public class MyCat extends AbstractCat implements Flyable{
// 1. ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค์์ ํด๋น ๊ณจ๊ฒฉ ๊ตฌํ์ ํ์ฅํ private ๋ด๋ถ ํด๋์ค๋ฅผ ์ ์ํ๋ค.
private MyFlyable myFlyable = new MyFlyable();
@Override
protected String sound() {
return "์ผ์น";
}
@Override
protected String name() {
return "amenable";
}
// 2. ๊ฐ ๋ฉ์๋ ํธ์ถ์ ๋ด๋ถ ํด๋์ค์ ์ธ์คํด์ค์ ์ ๋ฌํ๋ค.
@Override
public void fly() {
this.myFlyable.fly();
}
private class MyFlyable extends AbstractFlyable {
@Override
public void fly() {
System.out.println("๋ ์๋ผ");
}
}
}
----------
public static void main(String[] args) {
MyCat myCat = new MyCat();
System.out.println(myCat.sound()); // ์ผ์น
System.out.println(myCat.name()); // amenable
myCat.fly(); // ๋ ์๋ผ
}
ํด๋น ๊ธ์ ๋ฐฑ๊ธฐ์ ๋์ '์ดํํฐ๋ธ ์๋ฐ ์๋ฒฝ ๊ณต๋ต'์ ์ฐธ๊ณ ํ์์ต๋๋ค.