본문 바로가기
아카이브/자바의 정석

7장 20200925

by nineteen 2020. 9. 25.
반응형

제어자

 

클래스, 변수 또는 메소드의 선언부에 함께 사용되어 부가적인 의미를 부여

 

 

final

변수에 사용 - 상수가 됨

메소드에 사용 - 오버라이딩을 할 수 없게 됨

클래스에 사용 - 확장할 수 없는 클래스가 됨, 다른 클래스의 부모클래스가 될 수 없음

 

1
2
3
4
5
6
7
8
final class FinalTest {              // 부모가 될 수 없는 클래스
    final int MAX_SIZE = 10;        // 값을 변경할 수 없는 멤버변수(상수)
    
    final void getMaxSize() {        // 오버라이딩할 수 없는 메소드(변경불가)
        final int LV = MAX_SIZE;    // 값을 변경할 수 없는 지역변수(상수)
        return MAX_SIZE;
    }
}
cs

 

 

 

 

abstract

메소드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상메소드를 선언하는데 사용

 

추상클래스는 아직 완성되지 않은 메소드가 존재하는 '미완성 설계도'이므로 인스턴스 생성불가

 

1
2
3
abstract class AbstractTest {    // 추상클래스 (추상메소드를 포함한 클래스)
    abstract void move();        // 추상메소드 (구현부가 없는 메소드)
}
cs

 

 

 

 

 

 

제어자의 조합

 

1. 메소드에 static과 abstract를 함께 사용할 수 없다

2. 클래스에 abstract와 final을 동시에 사용할 수 없다

3. abstract메소드의 접근 제어자가 private일 수 없다

4. 메소드에 private과 final을 같이 사용할 필요는 없다

 

 

 

 

 

 

다형성(polymorphism)

 

여러가지 형태를 가질 수 있는 능력을 의미

-> 부모클래스 타입의 참조변수로 자식클래스의 인스턴스를 참조할 수 있도록 했다는 의미

 

ex)

CaptionTv c = new CaptionTv();

Tv t = new CaptionTv();  --> Tv클래스의 멤버들만 사용가능

 

둘다 같은 타입의 인스턴스지만 참조변수 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다

 

부모타입의 참조변수로 자식타입의 인스턴스를 참조할 수 있다

반대로 자식타입의 참조변수로 부모타입의 인스턴스를 참조할 수는 없다

 

 

 

 

 

 

참조변수의 형변환

 

자식타입 -> 부모타입(Up-casting) : 형변환 생략가능

자식타입 <- 부모타입(Down-casting) : 형변환 생략불가

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Car {
    String color;
    int door;
    
    void drive() {
        System.out.println("drive~");
    }
    
    void stop() {
        System.out.println("stop!");
    }
}
 
class FireEngine extends Car {
    void water() {
        System.out.println("water!!");
    }
}
 
public class CastingTest1 {
    public static void main(String[] args) {
        Car car = null;
        FireEngine fe = new FireEngine();
        FireEngine fe2 = null;
        
        fe.water();
        car = fe; // 형변환, 자식타입 -> 부모타입 (형변환생략)
        // car.water(); -> Car형으로는 water()메소드 호출불가
        fe2 = (FireEngine)car; // 형변환, 부모타입 -> 자식타입
        fe2.water();
 
    }
 
}
 
 
 
cs

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class CastingTest2 {
    public static void main(String[] args) {
        Car car = new Car();
        Car car2 = new FireEngine();
        FireEngine fe = null;
        
        car.drive();
        
        // 에러, 부모타입의 인스턴스를 자식타입의 참조변수로 참조하는것 허용 x
        // fe = (FireEngine)car;
        
        fe = (FireEngine)car2; // 실행 o
        fe.drive();    
    }
}
 
cs

 

서로 상속관계에 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나,

참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다.

그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요!

 

 

 

 

 

 

 

instanceof연산자

 

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof연산자 사용

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class InstanceofTest {
    public static void main(String[] args) {
        FireEngine fe = new FireEngine();
        
        if(fe instanceof FireEngine) {
            System.out.println("This is a Fire Engine instance");
        }
        
        if(fe instanceof Car) {
            System.out.println("This is a Car instance");
        }
        
        if(fe instanceof Object) {
            System.out.println("This is a Object instance");
        }
        
        System.out.println(fe.getClass().getName()); // 클래스의 이름 출력
    }
 
}
 
cs

출력

This is a Fire Engine instance

This is a Car instance

This is a Object instance

FireEngine 

 

 

어떤 타입에 대한 instanceof연산의 결과가 true라는 것은 검사한 타입으로 형변환이 가능하다는 뜻

 

 

 

 

 

 

 

 

 

참조변수와 인스턴스의 연결

 

멤버변수 - 참조변수의 타입에 따라 달라짐

메소드 -  부모클래스의 메소드를 자식클래스에서 오버라이딩한 경우에도 참조변수의 타입에 관계없이 항상 실제 인스턴스의 메소드(오버라이딩된 메소드)가 호출

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class A {
    int x = 100;
    
    void method() {
        System.out.println("Parent Method");
    }
}
 
class B extends A {
    int x = 200;
    
    void method() { // 오버라이딩
        System.out.println("Child Method");
    }
}
 
public class BindingTest {
    public static void main(String[] args) {
        A a = new B();
        B b = new B();
        
        // A클래스의 참조변수이므로 A클래스의 x값 출력
        System.out.println("a.x = " + a.x);
        a.method(); // 오버라이딩된 B클래스의 method()
        
        // B클래스의 참조변수이므로 B클래스의 x값 출력
        System.out.println("b.x = " + b.x);
        b.method();
    }
}
 
cs

출력

a.x = 100

Child Method

b.x = 200

Child Method 

 

 

메소드인 method()는 참조변수의 타입에 관계없이 실제 인스턴스의 타입인 B클래스에 정의된 메소드가 호출되지만,

인스턴스변수인 x는 참조변수의 타입에 따라 달라진다

 

 

 

 

 

 

 

 

 

다형성 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package polymorphism;
 
class Product {
    // 값, 보너스포인트
    // 변수구성
    int price;
    int bonusPoint;
    
    Product(int price) {
        this.price = price;
        bonusPoint = price/10;
    }
}
 
class Computer extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Computer() {
        super(200);
    }
    
    public String toString() {
        return "Computer";
    }
}
 
class Tv extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Tv() { // Tv클래스의 인스턴스 생성되면 Product클래스의 생성자 호출
        super(100);
    }
    
    public String toString() {
        return "TV";
    }
}
 
class Buyer {
    // 변수구성
    int money = 1000;
    int bonusPoint = 0;
    
    // 메소드, 다형성을 이용
    // 매개변수가 Product타입의 참조변수라는 것은,
    // 매개변수로 Product클래스의 자식타입의 참조변수면 매개변수로 사용가능하다는것
    void buy(Product p) {
        if(money < p.price) {
            System.out.println("돈이 부족해요");
            return;
        }
        money -= p.price;
        bonusPoint += p.bonusPoint;
        System.out.println(p + "을/를 구입하셨습니다.");
    }
    
}
 
public class PolyArgumentTest {
    public static void main(String[] args) {
        Buyer buyer = new Buyer();
        
        // Product클래스의 자식클래스인 Tv, Computer클래스의 인스턴스를 매개변수로 사용
        buyer.buy(new Tv());
        buyer.buy(new Computer());
        
        System.out.println("남은돈 : " + buyer.money);
        System.out.println("보너스포인트 : " + buyer.bonusPoint);
    }
 
}
 
 
 
 
 
cs

 

출력

TV을/를 구입하셨습니다
COMPUTER을/를 구입하셨습니다
남은돈 : 700
보너스포인트 : 30

 

 

 

 

배열 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package polymorphism;
 
class Product {
    // 값, 보너스포인트
    // 변수구성
    int price;
    int bonusPoint;
    
    Product(int price) {
        this.price = price;
        bonusPoint = price/10;
    }
}
 
class Computer extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Computer() {
        super(200);
    }
    
    public String toString() {
        return "Computer";
    }
}
 
class Tv extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Tv() { // Tv클래스의 인스턴스 생성되면 Product클래스의 생성자 호출
        super(100);
    }
    
    public String toString() {
        return "TV";
    }
}
 
class Buyer {
    // 변수구성
    int money = 1000;
    int bonusPoint = 0;
    Product[] item = new Product[10]; // Product형 담을 배열
    int i=0// 배열 인덱스 참조할 변수
    
    // 메소드, 다형성을 이용
    // 매개변수가 Product타입의 참조변수라는 것은,
    // 매개변수로 Product클래스의 자식타입의 참조변수면 매개변수로 사용가능하다는것
    void buy(Product p) {
        if(money < p.price) {
            System.out.println("돈이 부족해요");
            return;
        }
        money -= p.price;
        bonusPoint += p.bonusPoint;
        item[i++= p;
        System.out.println(p + "을/를 구입하셨습니다.");
    }
 
    void summary() {
        int sum=0;
        String itemList = "";
        
        for(int i=0; i<item.length; i++) {
            if(item[i] == nullbreak;
            itemList += item[i] + ", ";
            sum += item[i].price;
        }
        
        System.out.println("구매내역은 : " + itemList);
        System.out.println("구매총액은 : " + sum);
    }
    
}
 
public class PolyArgumentTest {
    public static void main(String[] args) {
        Buyer buyer = new Buyer();
        
        // Product클래스의 자식클래스인 Tv, Computer클래스의 인스턴스를 매개변수로 사용
        buyer.buy(new Tv());
        buyer.buy(new Computer());
        
        buyer.summary();
    }
 
}
 
 
 
 
 
cs

Buyer클래스에 Product를 담는 배열을 생성해 구매한 항목을 배열에 담고, 구매내역과 구매총액을 배열을 통해 계산했다

 

 

 

 

 

 

 

 

 

ArrayList활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package polymorphism;
 
class Product {
    // 값, 보너스포인트
    // 변수구성
    int price;
    int bonusPoint;
    
    Product(int price) {
        this.price = price;
        bonusPoint = price/10;
    }
}
 
class Computer extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Computer() {
        super(200);
    }
    
    public String toString() {
        return "Computer";
    }
}
 
class Tv extends Product {
    // 생성자통해 값, 보너스포인트 초기화
    Tv() { // Tv클래스의 인스턴스 생성되면 Product클래스의 생성자 호출
        super(100);
    }
    
    public String toString() {
        return "TV";
    }
}
 
class Buyer {
    // 변수구성
    int money = 1000;
    int bonusPoint = 0;
    Product[] item = new Product[10]; // Product형 담을 배열
    int i=0// 배열 인덱스 참조할 변수
    
    // 메소드, 다형성을 이용
    // 매개변수가 Product타입의 참조변수라는 것은,
    // 매개변수로 Product클래스의 자식타입의 참조변수면 매개변수로 사용가능하다는것
    void buy(Product p) {
        if(money < p.price) {
            System.out.println("돈이 부족해요");
            return;
        }
        money -= p.price;
        bonusPoint += p.bonusPoint;
        list.add(p); // 리스트에 구매항목 추가        
        System.out.println(p + "을/를 구입했어요.");
    }
    
    void refund(Product p) {
        if(list.remove(p)) { // 해당 품목 삭제
            // 금액과 보너스포인트 복구
            money += p.price;
            bonusPoint -= p.bonusPoint;
        } else {
            System.out.println("해당 품목이 없어요");
        }
    }
    
    void summary() {
        int sum=0;
        String itemList = "";
        
        for(int i=0; i<list.size(); i++) {
            Product p = (Product)list.get(i);
            sum += p.price;
            itemList += (i==0) ? "" + p : ", " + p;
        }
        
        System.out.println("구매내역은 : " + itemList);
        System.out.println("구매총액은 : " + sum);
    }
}
 
public class PolyArgumentTest {
    public static void main(String[] args) {
        Buyer buyer = new Buyer();        
        Computer com = new Computer();
        Tv tv = new Tv();
        Audio audio = new Audio();
 
        // Product클래스의 자식클래스인 Tv, Computer클래스의 인스턴스를 매개변수로 사용
        buyer.buy(com);
        buyer.buy(tv);
        buyer.buy(audio);
        buyer.summary();
        System.out.println();
        buyer.refund(audio);
        buyer.summary();    
    }
 
}
 
 
 
 
 
cs

 

 

 

 

 

 

 

 

 

 

 

 

추상클래스

 

미완성 셜계도

미완성 메소드(추상메소드)를 포함하고 있다는 의미

 

추상클래스로 인스턴스 생성 불가

추상클래스는 상속을 통해서 자식클래스에 의해서만 완성될 수 있다

 

새로운 클래스를 작성하는데 있어서 바탕이 되는 부모클래스로서 중요한 의미를 가짐

 

새로운 클래스를 작성할 때 아무것도 없는 상태에서 시작하는 것보다

완전하지는 못하더라도 어느 정도 틀을 갖춘 상태에서 시작하는 것이 나음

ex)

서로 다른 TV의 설계도를 따로 그리는 것보다,

이들의 공통부분만을 그린 미완성 설계도를 만들어 놓고 이 설계도를 이용해 각각의 설계도를 완성하는 원리

 

 

 

 

추상메소드

 

메소드의 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔것

 

메소드의 내용이 상속받는 클래스에 따라 달라질 수 있기 때문에 부모 클래스에서 선언부만 작성,

실제 내용은 상속받는 클래스에서 구현

 

추상클래스로부터 상속받는 자식클래스는 오버라이딩을 통해 부모인 추상클래스의 추상메소드를 모두 구현해야함

만약 부모로부터 상속받은 추상메소드를 모두 구현하지 않는다면, 자식클래스도 추상클래스로 지정해야함

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abstract class Player {             // 추상클래스
    abstract void play(int pos));    // 추상메소드
    abstract void stop();            // 추상메소드
}
 
class AudioPlayer extends Player {
    void play(int pos) {             // 추상메소드 구현 
        /* 내용생략 */ 
    }    
    void stop() {                     // 추상메소드 구현
        /* 내용생략 */ 
    } 
}
 
// 추상메소드를 전부 구현하지 않았기때문에 추상클래스로 
abstract class AbstractPlayer extends Player {    
    void play(int pos) {            // 추상메소드 구현
        /* 내용생략 */
    }
 
 
 
 
cs

 

 

 

 

 

추상클래스의 작성

 

여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 작성

기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하도록 하기도 함

 

상속계층도를 내려갈수록 클래스는 기능이 점점 추가되고 세분화

상속계층도를 올라갈수록 클래스는 추상화의 정도가 심해지고 공통요소만 남게됨

 

추상화 - 클래스간의 공통점을 찾아내서 공통의 부모를 만드는 작업

구체화 - 상속을 통해 클래스를 구현, 확장하는 작업

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
abstract class Unit {                         // 추상 클래스
    int x, y;
    abstract void move(int x, int y);        // 추상 메소드
    void stop() { /* 현재 위치에 정지 */ }
}
 
class Marine extends Unit {
    void move(int x, int y) {                // 추상클래스 상속받은 자식클래스에서 추상메소드 구현
        /* 지정된 위치로 이동 */
    }
 
    void stimPack() {
        /* 스팀팩 사용 */
    }    
}
 
class Tank extends Unit {
    void move(int x, int y) {                // 추상클래스 상속받은 자식클래스에서 추상메소드 구현
        /* 지정된 위치로 이동 */
    }
 
    void changeMode() {
        /* 공격모드로 변환 */
    }    
}
 
class Dropship extends Unit {
    void move(int x, int y) {                // 추상클래스 상속받은 자식클래스에서 추상메소드 구현
        /* 지정된 위치로 이동 */
    }
    
    void load() {
        /* 선택된 대상을 태운다 */
    }
 
    void unload() {
        /* 선택된 대상을 내린다 */
    }    
}
 
 
 
 
cs

 

 

 

 

 

 

 

 

인터페이스

 

인터페이스는 일종의 추상클래스

 

오직 추상메소드와 상수만을 멤버로 가질 수 있음

 

추상클래스를 부분적으로 완성된 '미완성 설계도'라고 한다면

인터페이스는 구현된 것이 아무 것도 없고 밑그림만 그려져 있는 '기본 설계도'라고 할 수 있다

 

다른 클래스를 작성하는데 도움을 줄 목적으로 작성됨

 

 

 

인터페이스 작성

 

- 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다

- 모든 메소드는 public abstract이어야 하며, 이를 생략할 수 있다 (static메소드와 디폴트 메소드는 예외)

 

1
2
3
4
interface 인터페이스이름 {
    public static final 타입 상수이름 = 값;
    public abstract 메소드이름(매개변수목록);
}
cs

 

ex)

1
2
3
4
5
6
7
8
9
interface PlayingCard {
    public static final int SPADE = 4;
    final int DIAMOND = 3;        // public static final int DIAMOND = 3;
    static int HEART = 2;        // public static final int HEART = 2;
    int CLOVER = 1;                // public static final int CLOVER = 1;
 
    public abstract String getCardNumber();
    String getCardKind();        // public abstract String getCardKind();
}
cs

 

 

 

 

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package interfaces;
 
interface Movable {
    void move(int x, int y);
}
 
interface Attackable {
    void attack(Unit u);
}
 
// Movable, Attackable인터페이스의 상속받음
interface Fightable extends Movable, Attackable {
 
}
 
class Unit {
    int currentHP;
    int x;
    int y;
}
 
// Unit클래스, Fightable인터페이스의 상속받음
class Fighter extends Unit implements Fightable {
    
    // 인터페이스의 메소드 구현
    public void move(int x, int y) {
        /* 내용 생략 */
    }
    
    public void attack(Unit u) {
        /* 내용 생략 */
    }
}
 
public class FighterTest {
    public static void main(String[] args) {
        Fighter f = new Fighter();
        
        if(f instanceof Unit)
            System.out.println("f는 Unit클래스의 자손입니다.");
        
        if(f instanceof Fightable)
            System.out.println("f는 Fightable인터페이스를 구현했습니다.");
        
        if(f instanceof Movable)
            System.out.println("f는 Movable인터페이스를 구현했습니다.");
        
        if(f instanceof Attackable)
            System.out.println("f는 Attackable인터페이스를 구현했습니다.");
        
        if(f instanceof Object)
            System.out.println("f는 Object클래스의 자손입니다.");
        
        
    }
}
 
 
cs

출력

f는 Unit클래스의 자손입니다.
f는 Fightable인터페이스를 구현했습니다.
f는 Movable인터페이스를 구현했습니다.
f는 Attackable인터페이스를 구현했습니다.
f는 Object클래스의 자손입니다.

 

 

 

 

 

 

인터페이스를 이용한 다중상속

 

두 클래스로부터 상속을 받을 수 없으므로, 

한 쪽만 선택하여 상속받고 나머지 한 쪽은 클래스 내에 포함시켜서 내부적으로 인스턴스를 생성해 사용

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package interfaces;
 
class Tv {
    protected boolean power;
    protected int channel;
    protected int volume;
    
    public void power() { power = !power; }
    public void channelUp() { ++channel; }
    public void channelDown() { --channel; }
    public void volumeUp() { ++volume; }
    public void volumeDown() { --volume; }
}
 
class VCR {
    protected int counter;
    
    public void play() {
        // tape재생
    }
    
    public void stop() {
        // 재생멈춤
    }
    
    public void reset() {
        counter = 0;
    }
    
    public int getCounter() {
        return counter;
    }
    
    public void setCounter(int c) {
        counter = c;
    }
}
 
// VCR클래스를 인터페이스화
interface IVCR {
    public void play();
    public void stop();
    public void reset();
    public int getCounter();
    public void setCounter(int c);
}
 
// Tv클래스, IVCR인터페이스 상속받음
public class TVCR extends Tv implements IVCR {
    // VCR클래스를 멤버변수로 포함시켜서 사용
    VCR vcr = new VCR();
 
    @Override
    public void play() {
        vcr.play();
        
    }
 
    @Override
    public void stop() {
        vcr.stop();
        
    }
 
    @Override
    public void reset() {
        vcr.reset();
        
    }
 
    @Override
    public int getCounter() {
        return vcr.getCounter();
    }
 
    @Override    public void setCounter(int c) {
        vcr.setCounter(c);        
    }
}
cs

 

 

 

 

 

 

인터페이스를 이용한 다형성

 

인터페이스는 인터페이스를 구현한 클래스의 부모라고 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조 할 수 있고, 인터페이스 타입으로 형변환도 가능하다

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package interfaces;
 
interface Parseable {
    public abstract void parse(String fileName);
}
 
// Parseable인터페이스의 상속받음
class XMLParser implements Parseable {
    public void parse(String fileName) {
        System.out.println(fileName + "- XML parsing completed");
    }
}
 
//Parseable인터페이스의 상속받음
class HTMLParser implements Parseable {
    public void parse(String fileName) {
        System.out.println(fileName + "- HTML parsing completed");
    }
}
 
class ParserManager {
    // 반환형이 Parseable인터페이스 형, 인터페이스를 이용한 다형성
    public static Parseable getParser(String type) {
        if(type.equals("XML")) {
            return new XMLParser(); 
        } else {
            Parseable p = new HTMLParser();
            return p; // 리턴타입이 인터페이스, 인터페이스를 구현한 클래스의 인스턴스 반환
        }
    }
}
 
public class ParserTest {
    public static void main(String[] args) {
        Parseable parser = ParserManager.getParser("XML"); // Parseable paser = new XMLParser();
        parser.parse("document.xml");
        parser = ParserManager.getParser("HTML");
        parser.parse("document.xml");
    }
}
 
cs

출력

document.xml - XML parsing completed

document.xml - HTML parsing completed

 

 

 

--> 인터페이스를 이용한 다형성을 구현한 예제

XMLParser와 HTMLParser클래스가 Parseable인터페이스를 구현하므로,

Parseable인터페이스가 두 클래스의 부모격이 된다

 

getParser()의 반환형이 Parseable이므로 인터페이스를 활용해 이를 구현한 클래스들을 참조할 수 있다

'아카이브 > 자바의 정석' 카테고리의 다른 글

8장 예외처리 20201009  (0) 2020.10.09
7장 20200926  (0) 2020.09.26
7장 20200924  (0) 2020.09.24
7장 상속 20200921  (0) 2020.09.21
6장 객체지향프로그래밍(2) 20200919  (0) 2020.09.19