본문으로 바로가기
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


자바 인터페이스(Interface) 정리


공부를 하면서 인터페이스의 필요에 대해 잘 몰랐고 최근 안드로이드를 공부하고 패턴을 응용하여 공부하게 되면서 인터페이스의 필요와 사용법을 정말 조금이나마 알게되었습니다

실제로 잘 사용하지 못하더라도 알고만 있다면 나중에 도움이 될 것 같아 작성하였습니다.


1. 인터페이스

객체와 객체의 소통 수단입니다.

다양한 객체를 제품의 부속품처럼 개발자 마음대로 변경할 수 있습니다.

자바의 다형성을 가능하게 합니다.(제일 이해하기 힘들었었던 부분..)

인터페이스는 객체가 아닙니다. 다만, 객체 타입으로만 사용됩니다.

추상메소드와 상수만 존재합니다.

상수를 만들 때 private 접근 제한자는 사용할 수 없습니다. 

super키워드를 사용할 수 없다.


예제를 위해 인터페이스 2개를 만들어서 Class에 상속하여 사용하는 예제를 아래에 작성하였습니다.
InterfaceSample1과 InterfaceSample2를 보면 추상 메소드와 상수만 존재한다는 것을 확인할 수 있습니다. 
package interfacestudy;

public interface InterfaceSample1 {
    public static final int NUM = 1000;
    
    public void cal();

}

package interfacestudy;

public interface InterfaceSample2 {
    
    public static final String STRING = "Hello ktkoWorld!";
    
    public String getString();

}

Interface를 클래스에 사용하기 위해 implements를 사용할 수 있다. 또한 단일 상속이 아닌 여러개를 상속받아 사용할 수 있습니다.

package interfacestudy; public class InterfaceClass implements InterfaceSample1, InterfaceSample2{ @Override public String getString() { System.out.println("InterfaceSample2을 재정의 하였습니다."); return ""; } @Override public void cal() { System.out.println("InterfaceSample1을 재정의 하였습니다."); } }



package interfacestudy;

public class Main {
    public static void main(String[] args) {
        InterfaceClass inter = new InterfaceClass();
        inter.cal();
        inter.getString();
    }
}

실행을 하면 아래와 같이 나옵니다.


InterfaceSample1을 재정의 하였습니다. 

InterfaceSample2을 재정의 하였습니다.


이제 MainClass의 새로운 예제를 보면

package interfacestudy; public class Main { public static void main(String[] args) { InterfaceClass inter = new InterfaceClass(); inter.cal(); inter.getString(); System.out.println("InterfaceSample1의 상수 : " + inter.NUM + " InterfaceSample2의 상수 : " + inter.STRING); System.out.println("\n"); InterfaceSample1 is1 = new InterfaceClass(); is1.cal(); System.out.println(is1.NUM); System.out.println("\n"); InterfaceSample2 is2 = new InterfaceClass(); is2.getString(); System.out.println(is2.STRING);

} }


InterfaceClass를 선언하고 생성하여 만들어진 객체 inter은 두개의 interface에서 선언된 두개의 메소드와 상수를 접근할 수 있습니다. 하지만 !

interface인 InterfaceSample1 과 InterfaceSampl2로 선언되었고 생성은 InterfaceClass로 만들어진 객체 is1과 is2는 선언된 인터페이스의 상수와 메소드만 접근하여 사용할 수 있다는 것을 알 수 있습니다.


결과를 보면 아래와 같습니다.

InterfaceSample1을 재정의 하였습니다.

InterfaceSample2을 재정의 하였습니다.

InterfaceSample1의 상수 : 1000 InterfaceSample2의 상수 : Hello ktkoWorld!



InterfaceSample1을 재정의 하였습니다.

1000


InterfaceSample2을 재정의 하였습니다.

Hello ktkoWorld!


컴퓨터 제작을 통한 Interface의 이해


컴퓨터에는 다양한 기능이 있습니다.

ktko전자에서 다양한 컴퓨터를만들고 스펙은 아래와 같습니다.

각 제품에 대한 스펙을 출력하려고 할 때 인터페이스를 활용하면 쉽게 출력할 수 있습니다.

 

스피커

무선 네트워크

SSD 

I제품

 ㅇ

S제품

 ㅇ

A제품

 ㅇ

 ㅇ


인터페이스를 생성하고 각 기능에 대해 사용 가능한지 출력하기 위해 메소드를 인터페이스에 선언합니다.

package interfacestudy;

public interface CFunction {
    public void comSpeaker();
    public void wirelessNetwork();
    public void comSSD();
}


각 제품별 사용 가능여부를 출력하기 위해 인터페이스를 implements 를 상속받습니다. 

package interfacestudy;

public class AComputer implements CFunction{
    @Override
    public void comSpeaker() {
        // TODO Auto-generated method stub
        System.out.println("스피커 사용 가능 합니다.");
    }
    @Override
    public void comSSD() {
        // TODO Auto-generated method stub
        System.out.println("SSD 사용 가능 합니다.");
    }
    @Override
    public void wirelessNetwork() {
        // TODO Auto-generated method stub
        System.out.println("무선네트워크 사용 가능 합니다.");
    }
}

package interfacestudy;

public class IComputer implements CFunction{
    @Override
    public void comSpeaker() {
        // TODO Auto-generated method stub
        System.out.println("스피커 사용 가능 합니다.");
    }
    @Override
    public void comSSD() {
        // TODO Auto-generated method stub
        System.out.println("SSD 사용 불가능 합니다.");
    }
    @Override
    public void wirelessNetwork() {
        // TODO Auto-generated method stub
        System.out.println("무선네트워크 사용 불가능 합니다.");
    }
}


package interfacestudy;

public class SComputer implements CFunction{
    @Override
    public void comSpeaker() {
        // TODO Auto-generated method stub
        System.out.println("스피커 사용 가능 합니다.");
    }
    @Override
    public void comSSD() {
        // TODO Auto-generated method stub
        System.out.println("SSD 사용 가능 합니다.");
    }
    @Override
    public void wirelessNetwork() {
        // TODO Auto-generated method stub
        System.out.println("무선네트워크 사용 가능 합니다.");
    }
}

여기서 중요!!

각 제품에 대해 객체를 생성하여 API를 호출하는데 아래와 같이 복잡하게 할 필요가 있을까 ? 

다형성을 이용하여 간단하게 호출할 수 있는 방법이있다.

package interfacestudy; public class Main { public static void main(String[] args) { AComputer ac = new AComputer(); IComputer ic = new IComputer(); SComputer sc = new SComputer(); ac.comSpeaker(); ac.comSSD(); ac.wirelessNetwork(); ic.comSpeaker(); ic.comSSD(); ic.wirelessNetwork(); sc.comSpeaker(); sc.comSSD(); sc.wirelessNetwork(); } }


아래와 같이 인터페이스로 객체를 생성하는 것이 아닌 선언을 하고 각 클래스를 생성하여 선언한다면 쉽게 객체들을 관리할 수 있다.

package interfacestudy; public class Main { public static void main(String[] args) { CFunction acom = new AComputer(); CFunction icom = new IComputer(); CFunction scom = new SComputer(); CFunction[] cFunctions = {acom, icom, scom}; for (int i = 0; i < 3; i++) { cFunctions[i].comSpeaker(); cFunctions[i].comSSD(); cFunctions[i].wirelessNetwork(); System.out.println(); } } }


직업을 통한 Interface의 이해

다양한 사람들은 직업을 가지고 있습니다. 어떤 사람은 프로그래머를, 어떤 사람은 경찰을, 어떤 사람은 소방관을 일한다고 가정했을 때 다형성을 이용한 예제를 만들어 보겠습니다.

먼저 각 직업에 대한 인터페이스를 만들고 함수를 만들었습니다.


소방관의 Interface

package interfacestudy;
 
public interface Firefighter {
    void outFire();
    void saveMan();
}


경찰관의 Interface

package interfacestudy;

public interface Policeman {
    void catchCriminal();
    void canSearch();
}


프로그래머의 Interface



package interfacestudy;

public interface Programmer {
    void coding();
    void makeApplication();
}


직업 클래스에 위에 선언한 인터페이스를 상속받고 구현해줍니다.

package interfacestudy; public class Job implements Firefighter, Policeman, Programmer{ @Override public void coding() { System.out.println("Programmer : 코딩을 합니다."); } @Override public void makeApplication() { // TODO Auto-generated method stub System.out.println("Programmer : 어플리케이션을 만듭니다."); } @Override public void catchCriminal() { // TODO Auto-generated method stub System.out.println("Policeman : 범죄를 잡습니다."); } @Override public void canSearch() { // TODO Auto-generated method stub System.out.println("Policeman : 물건 또는 사람을 찾습니다."); } @Override public void outFire() { // TODO Auto-generated method stub System.out.println("Firefighter : 불을 끕니다."); } @Override public void saveMan() { // TODO Auto-generated method stub System.out.println("Firefighter : 사람을 구합니다."); } }


!여기서 중요.

Job이라는 클래스를 통해 객체를 생성한다면 각 직업에 대한 모든 일을 처리할 수 있습니다.

하지만 개발을 하는 사람 입장에서 이런 처리는 실수를 유발하게 됩니다. 아래 실수에 대한 예제를 만들어봤습니다. Job클래스를 통해 프로그래머 직업에 대한 일을 처리하려하였지만 모든 인터페이스에 대한 Method를 가지고 있어 아래와같은 실수를 할 수 있습니다.

package interfacestudy;

public class InterfaceMain {
    public static void main(String[] args) {
        Job programmer = new Job();
        programmer.canSearch();
        programmer.catchCriminal();
    }
}


다형성을 활용하여, 각 직업에 대해 정의한 인터페이스로 선언을 하고 생성을 Job라는 클래스를 통해 하게 된다면 실수를 줄이고 각 직업에 대한 Method를 활용할 수 있습니다.

package interfacestudy;

public class InterfaceMain {
    public static void main(String[] args) {
        Job person = new Job();
Job.canSearch();
Job.catchCriminal();
Job.coding();
Job.makeApplication();
Job.outFire();
Job.saveMan();
Policeman policeman = new Job();
policeman.canSearch(); policeman.catchCriminal(); Programmer programmer = new Job();
programmer.coding(); programmer.makeApplication(); Firefighter firefighter = new Job();
firefighter.outFire(); firefighter.saveMan(); } }