본문 바로가기

# 02/Java

[윤성우 열혈자바] 17-2. 인터페이스의 문법 구성과 추상 클래스

반응형

인터페이스에 선언되는 메소드와 변수


인터페이스는 외부에서 클래스가 사용하는 방법을 명시하는 것이므로 외부에서 사용할 수 있게 public으로 인식함.


interface Printable {

public void print(String doc);            // 추상 메소드. 무조건 public임 선언하지 않아도 default가 아니라 public으로 인식함.

}



interface Printable {

public static final int PAPER_WIDTH = 70;

public static final int PAPER_HEIGHT = 120;

public void print(String doc);

}


인터페이스는 인스턴스 생성이 불가하므로 인스턴스 변수 생성 할 수 없음!!


단, 상수 선언 가능!!


변수 는 무조건 public static final을 자동으로 인식함!!








인터페이스간 상속 : 문제 상황의 제시


interface Printable {

void print( String doc );

void printCMYK ( String doc );

}

컬러 출력 위한 메소드 추가되면? 

기존 인터페이스에 컬러출력을 위한 메소드를 추가하면

다른 흑백프린트에도 컬러출력을 위한 추상 메소드를 무조건 구현해야 됨!! 

-> 시스템 전체에 문제 발생


class SPrinterDriver implements Printable {


@Override

public void print (String doc) { ... }


// 이 클래스에서 printCMYK 메소드 구현해야 함

}



class LPrinterDriver implements Printable {

@Override

public void print (String doc) { ... }

// 이 클래스에서 printCMYK 메소드 구현해야 함

}


인터페이스를 구현하는 클래스는 해당 인터페이스의 모든 추상 메소드를 구현해야 한다. 그래야 인스턴스 생성 가능!!!









제시한 문제의 해결책 : 인터페이스의 상속


interface Printable {

void print (String doc);

}



인터페이스간 상속도 extends로 표현

interface ColorPrintable extends Printable {

void printCMYK(String doc);

}



class SPrinterDriver implements Printable {

...

}    // 기존 클래스 수정할 필요 없음




class Prn909Drv implements ColorPrintable {

@Override

public void print(String doc) {                    // 흑백 출력

System.out.println("black & white ver");

System.out.println(doc);

}


@Override

public void printCMYK (String doc) {            // 컬러 출력

System.out.println("CMYK ver");

System.out.println(doc);

}

}









인터페이스의 디폴트 메소드 : 문제 상황의 제시


총 256개의 인터페이스가 존재하는 상황에서 모든 인터페이스에 다음 추상 메소드를 추가해야 한다면?

(예, 자바에서 람다)


void printCMYK(String doc);


인터페이스간 상속?


물론 인터페이스간 상속으로 문제 해결 가능하다. 다만 인터페이스의 수가 256개 늘어날 뿐이다.



다음 디폴트 메소드로 이 문제를 해결하면 인터페이스의 수가 늘어나지 않는다.


default void printCMYK (String doc) { }                    // 디폴트 메소드


원래 인터페이스의 메소드는 추상메소드로 몸체를 {} 가지고 있지 않는다.


디폴트 메소드는 몸체를 가지고 있고 구현을 해도 되고 하지 않아도 된다.









디폴트 메소드의 효과


interface Printable {

void print(String doc);

}


-> 인터페이스 교체

interface Printable {

void print(String doc);

default void printCMYK(String doc) { }

}



class SPrinterDriver implements Printable {

@Override

public void print(String doc) { ... }

}

기존에 정의된 클래스 : 인터페이스 교체로 인해 코드 수정 필요 없다.



class Prn909Drv implements Printable {

@Override

public void print(String doc) { ... }


@Oberride

public void printCMYK(String doc) { ... }

}

새로 정의된 클래스









인터페이스의 static 메소드


"인터페이스에도 static 메소드를 정의할 수 있다."


"그리고 인터페이스의 static 메소드 호출 방법은 클래스의 static 메소드 호출 방법과 같다."


interface Printable {

static void printLine (String str) {

System.out.println(str);

}


default void print(String doc) {

printLine(doc);                    // 인터페이스의 static 메소드 호출

}

}










인터페이스 대상의 instanceof 연산


if (ca instanceof Cake) . . .


Cake 클래스의 이름도, 인터페이스의 이름도 될 수 있다.


ca가 참조하는 인스턴스를 Cake 형 참조변수로 참조할 수 있으면 true 반환!


ca가 참조하는 인스턴스가 Cake를 직접 혹은 간접적으로 구현할 클래스의 인스턴스인 경우 true 반환!


interface Printable {

void printLine(String str);

}


class SimplePrinter implements Printable {

public void printLine (String str) {

System.out.println(str);

}


class MultiPrinter extends SimplePrinter {

public void printLine(String str) {

super.printLine("start of multi...");

super.printLine(str);

super.printLine("end of multi");

}

}


public static void main(String[] args) {

Printable prn1 = new SimplePrinter();

Printable prn2 = new MultiPrinter();


if(prn1 instanceof Printable)

prn1.printLine("This is a simple printer.");

System.out.println();


if(prn2 instanceof Printable)

prn2.printLine("This is a multiful printer.");

}


This is a simple printer.

start of multi...

This is a multiful printer.

end of multi








인터페이스의 또 다른 용도 : Marker 인터페이스


interface Upper { }                 // 마커 인터페이스 - 메소드 정의 하지 않음!!

interface Lower { }                 // 마커 인터페이스


interface Printable {

String getContents();

}


class Report implements Printable, Upper {

String cons;


Report(String cons) {

this.cons = cons;

}


public String getContents() {

return cons;

}

}


public void printContents (Printable doc) {

if(doc instanceof Upper) {

System.out.println((doc.getContents()).toUpperCase());

}

else if(doc instanceof Lower) {

System.out.println((doc.getContents()).toLowerCase());

}

else

System.out.println(doc.getContents());

}


클래스에 특정 표시를 해 두기 위한 목적으로 정의된 인터페이스를 마커 인터페이스라고 한다.


마커 인터페이스에는 구현해야 할 메소드가 없는 경우가 흔하다.










추상 클래스


public abstract class House {                        // 추상 클래스 - abstract 선언 무조건 해줘야됨!!!!!

public void methodOne() {

System.out.println("method one");

}


public abstract void methodTwo();            // 추상 메소드 - abstract 선언 무조건 해줘야됨!!!!!

}


하나 이상의 추상 메소드를 지니는 클래스를 추상 클래스라 한다.


그리고 추상 클래스를 대상으로는 인스턴스 생성이 불가능하다. 물론 참조변수 선언은 가능하다.


추상 클래스는 참조변수 선언 가능 인터페이스도 가능


추상 클래스는 인스턴스 변수, 인스턴스 메소드 선언 가능 인터페이스는 인스턴스 변수, 인스턴스 메소드 선언 불가


추상 클래스는 인스턴스 생성은 불가함. 상위클래스로만 남기고 싶을때 사용!


반응형