ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [자바] 인터페이스
    자바 2022. 8. 5. 21:38
    728x90

    - 일종의 추상클래스이다. ( 추상 클래스 보다 추상화가 더 되어 있다. )

    - 오직 추상 메서드와 상수만 멤버로 갖는다 

     

    어떤 클래스가 있고 인터페이스 사용시 그 클래스는 반드시 인터페이스에 있는 메소드를 사용하게끔 강제한다.

     

    interface I {
        public void z(); // 구현부 (몸통) 이 없어야 한다
    }
    
    class A implements I {
        public void z(){} // 구현은 여기서 한다.
    }

     

    인터페이스 규칙

    1. 하나의 클래스는 복수개의 인터페이스 구현 가능

    interface I1 {
        public void x(); // 구현 ㄴ
    }
    interface I1 {
        public void z();
    }
    
    class A implements I1, I2 {
        public void x() {} // 구현필수
        public void z() {} // 구현필수
    }

     

    2. 인터페이스도 상속이 된다

    interface I3 {
        public void x(); // 구현 ㄴ
    }
    interface I4 extends I3 {
        public void z();
    }
    
    class A implements I4 {
        public void x() {} // 구현필수
        public void z() {} // 구현필수 
    }

     

    3. 인터페이스의 멤버는 public 이여야만 한다

     

    인터페이스 작성방식

    interface 인터페이스이름 {
        public static final 타입 상수이름 = 값;
        public abstract 메서드이름(매개변수 목록);
    }
    - 모든 멤버변수는 public static final ( 생략가능 ) - 접근제어자 public 명심
    - 모든 메서드는 public abstract ( 생략가능 ) - 접근제어자 public 명심

     

    - 인터페이스는 다중 상속이 가능하다.

     

    인터페이스 구현

    - 인터페이스는 자체로 인스턴스를 생성할 수 없다.

     

    추상 클래스가 상속을 통해 추상 메서드를 완성하듯 implements를 통해 클래스 작성

    class 클래스 이름 implements 인터페이스이름 { }
    
    class Fighter implements Fightable {
        public void move(int x, int y) { /* */ }
        public void attack(Unit u) { /* */ }
    }

     

    만일, 인터페이스의 메서드 중 일부만 구현하면 abstract   붙여줘야 한다.

    abstract class Fighter implements Fightable {
        public void move(int x, int y) { /* */ }
    }

     

    상속과 구현을 동시에 할 수 있다.

    class Fighter extends Unit implements Fightable {
        public void move(int x, int y) { /* */ }
        public void attack(Unit u) { /* */ }
    }

     

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

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

     

    인터페이스 Fightable을 클래스 Fighter가 구현했을때

    Fightable f = new Fighter();
    // Fightable 이라는 인터페이스
    // Fighter 이라는 클래스

     

    메서드의 매개변수의 타입도 가능

    void attack(Fightable f) { }

     

    인터페이스 타입의 매개변수가 갖는 의미는 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는것이다

    Fiahtable method() {
        Fighter f = new Fighter();
        return f;
        
        // 위의 두줄을 윗말대로 줄여보면
        // return new Fighter(); // 인스턴스를 반환하고 있다
    }

     

     

    class Fighter extends Unit implements Fightable {
        void attack(Fightable f) { }
    }

     

    정말 중요한것!

    Fightable method() {
        Fighter f = new Fighter();
        return f;
    }

    리턴 타입이 인터 페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.

     

    interface Parseable {
        public static void parse(String fileName);
    }
    
    class ParserManager {
        // 리턴타입이 Parseable 인터페이스이다.
        public static void main(String[] args) {
            if( type.equals("XML")) {
                return new XMLParser();
            } else {
                Parseable p = new HTMLParseable();
                return p;
            }
        }
    }
    
    class XMLParser implements Parseable {
        public void parse(String fileName) {
            System.out.println(fileName);
        }
    }
    
    class HTMLParser implements Parseable {
        public void parse(String fileName) {
            System.out.println(fileName);
        }
    }
    
    class ParserTest {
        public static void main(String[] args) {
            Parseable parser = ParserManager.getParser("XML");
            parser.parse("xml");
            parser = ParserManager.getParser("HTML");
            parser.parse("html");
        }
    ]

    getParser 매서드는 매개변수로 넘겨받는 type에 따라 값이 XMLParser 인스턴스 또는 HTMLParser 인스턴스 반환한다

    이렇게 하면, 프로그램 자체를 변경하지 않고, 서버측의 변경만으로 사용자가 새로 개전된 프로그램을 사용할 수 있다.

     

    인터페이스 이해

    직접적인 관계

    A( User ) -> B ( Provider ) : 직접적인 관계 , B가 바뀌면 A도 바뀌어야함
    class A {
        public void method(B b) {
            b.methodB();
        }
    }
    
    class B {
        public void method() {
            System.out.println("method b");
        }
    }
    
    class InterfaceTest {
        public static void main(String[] args) {
            A a = new A();
            a.methodA(new B());
        }
    }

     

     

    간접적인 관계로 바꾸기 위해서는 인터페이스를 통해 클래스 B의 선언과 구현 분리 필요

    간접적으로 'A-I-B' 관계 : A는 인터페이스의 영향만 직접적으로 받는다 ( B의 영향을 받지 않는다.)
    class A {
        public void method(I i) { // 이 부분이 중요
            i.methodB(); // 이 부분이 중요
        }
    }
    
    interface I {
        public abstract void methodB();
    }
    
    class B implements I {
        public void method() {
            System.out.println("interface method b");
        }
    }
    
    class InterfaceTest {
        public static void main(String[] args) {
            A a = new A();
            a.methodA(new B());
        }
    }

     

    인스턴스를 직접 생성하지 않고, getInstance() 라는 메서드를 통해 제공 받는다 

    나중에 다른 클래스의 인스턴스로 변경되어도 A클래스의 변경없이 getInstance()만 변경하면 된다는 장점이 있다

    class InterfaceTest {
        public static void main(String[] args) {
            A a = new A();
            a.methodA();
        }
    }
    
    class A {
        void method() {
            I i = InstanceManager.getInstance();
            i.methodB();
            System.out.println(i.toString());
        }
    }
    
    interface I {
        public abstract void methodB();
    }
    
    class B implements I {
        public void method() {
            System.out.println("interface method b");
        }
        public String toString() { return "class B" }
    }
    
    class InstanceManager {
        public static I getInstace() {
            return new B(); // 다른 인스턴스로 바꾸려면 여기만 바꾸면 된다
        }
    }

    인터페이스 I 타입의 참조변수 i로도 Object 클래스에 정의된 메서들을 호출 가능하다 ( toString() 이런 메서드 )

    '자바' 카테고리의 다른 글

    [자바] 참조  (0) 2022.08.06
    [자바] 다형성  (0) 2022.08.06
    [자바] final  (0) 2022.08.05
    [자바] abstract 추상  (0) 2022.08.05
    [자바] 접근제어자  (0) 2022.08.05
Designed by Tistory.