[Java] Interface

정재현·2024년 1월 3일

Java

목록 보기
31/43
post-thumbnail

인터페이스

  • 다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미
  • 다중 상속 가능
  • 인터페이스의 구현 클래스들은 반드시 정의된 메서드들을 구현해야 함

인터페이스 역할

  • 두 객체를 연결해주는 다리 역할

인터페이스의 멤버

  • 모든 멤버변수는 public static final 으로 구성
    • 해당 키워드는 생략 가능
  • 모든 메서드는 public abstract으로 구성
    • 해당 키워드는 생략 가능 (static 메서드와 default 메서드 예외)
  • 생략되는 제어자는 컴파일러가 자동으로 추가 해줌.
	public interface 인터페이스명 { 
			public static final char A = 'A';
	    static char B = 'B';
	    final char C = 'C';
	    char D = 'D';

	    void turnOn(); // public abstract void turnOn();
	}

인터페이스 구현

  • 직접 인스턴스를 생성할 수 없기 때문에 클래스에 구현되어 생성
  • implements 키워드를 사용하여 인터페이스를 구현
  • 인터페이스의 추상 메서드는 구현될 때 반드시 오버라이딩 되어야 한다.
  • 만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 해당 클래스를 추상 클래스로 변경해주면 됨
	public class 클래스명 implements 인터페이스명 { 
		// 추상 메서드 오버라이딩
		@Override
	    public 리턴타입 메서드이름(매개변수, ...) {
		       // 실행문
	    }
	}

인터페이스 상속

  • 인터페이스간의 상속 가능
  • extends 키워드를 이용해 상속 가능
  • 인터페이스는 클래스와 다르게 다중 상속이 가능

인스턴스 멤버 vs 클래스 멤버

  • 멤버 = 필드 + 메서드
  • 인스턴스 멤버 = 인스턴스 필드 + 인스턴스 메서드
    • 객체 생성 후에 사용 가능
  • 클래스 멤버 = 클래스 필드 + 클래스 메서드
    • 객체 생성 없이 사용 가능

필드와 메서드는 선언하는 방법에 따라서 인스턴스 멤버클래스 멤버로 구분할 수 있다.

인스턴스 멤버

  • 객체 생성 후에 사용 가능
  • 객체의 인스턴스 필드는 각각의 인스턴스 마다 고유하게 값을 가질 수 있다.
  • 인터페이스는 클래스와 마찬가지로 public, default 접근 제어자를 지정 가능
  • 생성 방법
    • interface 키워드를 사용하여 생성
	public interface 인터페이스명 { 

	}

클래스 멤버

  • 메서드 영역의 클래스와 같은 위치에 고정적으로 위치하고 있는 멤버를 의미
    • 따라서 클래스 멤버는 객체의 생성 필요없이 바로 사용이 가능
  • 일반적으로 인스턴스마다 모두 가지고 있을 필요없는 공용적인 데이터를 저장하는 필드는 클래스 멤버로 선언하는 것
  • 생성 방법
    • static 키워드로 생성
	static type 변수명 = 초기화;
  • 사용 방법
	Class명 Class변수 = new Class명();	// 객체 생성
    Class변수.클래스_멤버명 = 초기화;
  • 주의사항
    • 클래스 멤버로 선언된 메서드는 인스턴스 멤버를 사용할 수 없다.
      • 클래스 멤버는 객체 생성없이 바로 사용 가능하기 때문에 객체가 생성되어야 존재할 수 있는 인스턴스 멤버를 사용할 수 없다.
    • 반대로 인스턴스 멤버로 선언된 메서드는 클래스 멤버를 사용할 수 있다.

default 메서드 vs Static 메서드

default 메서드

  • 추상 메서드의 기본적인 구현을 제공하는 메서드
  • 메서드 앞에 default 키워드를 붙이며 블럭{ }이 존재해야 함.
  • default 메서드 역시 접근 제어자가 public 이며 생략이 가능
  • 추상 메서드가 아니기 때문에 인터페이스의 구현체들에서 필수로 재정의 할 필요는 없다.
	public class Main implements A {
	
    	@Override
    	public void a() {
    	    System.out.println("A");
    	}


    	public static void main(String[] args) {
    	    Main main = new Main();
    	    main.a();
	
	        // 디폴트 메서드 재정의 없이 바로 사용가능합니다.
	        main.aa();
	    }
	}

	interface A {
	    void a();
	    default void aa() {
	        System.out.println("AA");
	    }
	}

Static 메서드

  • 인터페이스에서 static 메서드 선언이 가능
  • static의 특성 그대로 인터페이스의 static 메서드 또한 객체 없이 호출이 가능
  • 선언하는 방법과 호출하는 방법은 클래스의 static 메서드와 동일
    • 접근 제어자를 생략하면 컴파일러가 public을 추가해줌
	public class Main implements A {

	    @Override
	    public void a() {
	        System.out.println("A");
	    }
	
	    public static void main(String[] args) {
	        Main main = new Main();
	        main.a();
	        main.aa();
	        System.out.println();
	
	        // static 메서드 aaa() 호출
	        A.aaa();
	    }
	}
	
	interface A {
	    void a();
	    default void aa() {
	        System.out.println("AA");
	    }
	    static void aaa() {
	        System.out.println("static method");
	    }
	}

인터페이스의 다형성

자동 타입변환 vs 강제 타입변환

  • 자동 타입변환
    • 인터페이스 변수 = 구현객체; 는 자동으로 타입 변환이 발생
	public class Main {
	    public static void main(String[] args) {
	        
	        // A 인터페이스에 구현체 B 대입
	        A a1 = new B();
	        
	        // A 인터페이스에 구편체 B를 상속받은 C 대입
	        A a2 = new C();        
	    }
	}

	interface A { }
	class B implements A {}
	class C extends B {}
  • 강제 타입변환
    • 구현객체타입 변수 = (구현객체타입) 인터페이스변수;
	public class Main {
	    public static void main(String[] args) {

	        // A 인터페이스에 구현체 B 대입
	        A a1 = new B();
	        a1.a();
	        // a1.b(); // 불가능
	
	        System.out.println("\nB 강제 타입변환");
	        B b = (B) a1;
	        b.a();
	        b.b(); // 강제 타입변환으로 사용 가능
	        System.out.println();
	
	        // A 인터페이스에 구편체 B를 상속받은 C 대입
	        A a2 = new C();
	        a2.a();
	        //a2.b(); // 불가능
	        //a2.c(); // 불가능
	
	        System.out.println("\nC 강제 타입변환");
	        C c = (C) a2;
	        c.a();
	        c.b(); // 강제 타입변환으로 사용 가능
	        c.c(); // 강제 타입변환으로 사용 가능
	    }
	}

	interface A {
	    void a();
	}
	class B implements A {
	    @Override
	    public void a() {
	        System.out.println("B.a()");
	    }
	
	    public void b() {
	        System.out.println("B.b()");
	    }
	}
	class C extends B {
	    public void c() {
	        System.out.println("C.c()");
	    }
	}

profile
공부 기록 보관소

0개의 댓글