Java

이것이 자바다 8장 [인터페이스] - 개념정리 및 확인문제

코드사냥꾼 2019. 11. 24. 15:47

1. 인터페이스

인터페이스란 객체의 사용 방법을 정의한 타입으로서 객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다. 인터페이스를 사용하면 개발 코드를 수정하지 않고, 사용하는 객체를 변경할 수 있기 때문에 실행 내용과 리턴 값을 다양화할 수 있다는 장점을 가진다. 인터페이스는 상수와 메서드만을 구성 멤버로 가지며 객체로 생성할 수 없기 때문에 생성자를 가질 수 없다. ( = 객체의 메서드를 호출시키기 때문) 자바 8부터는 디폴트 메서드와 정적 메서드도 선언이 가능해졌다.

💡 인터페이스 기본 구조와 선언 예

public interface 인터페이스명 { 

    // 상수
    타입 상수명 = 값;
    
    // 추상 메소드
    타입 메소드명(매개변수, ...);
    
    // 디폴트 메소드
    default 타입 메소드명(매개변수,...) {   }
    
    // 정적 메소드
    static 타입 메소드명(매개변수) {   }
    
}
  • 상수 필드 :  인터페이스에 고정된 값으로 런타임 시 데이터를 바꿀 수 없다. 반드시 초기값 대입이 필요하며 상수는 public static final로 선언하는데 각각 하나씩 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다. 

  • 추상 메소드 : 객체가 가지고 있는 메서드를 설명한 것으로 호출할 때 어떤 매개 값이 필요하고, 리턴 타입이 무엇인지만 알려준다. 실제 실행부는 객체(구현 객체)가 가지고 있다. public abstract의 특성을 갖기 때문에 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다.

  • 디폴트 메소드 : 객체(구현 객체)가 가지고 있는 인스턴스 메서드라고 생각하면 편하며 기존 인터페이스를 확장해서 새로운 기능을 추가하기 위해 허용된 메서드이다. default 키워드가 리턴 타입 앞에 붙고 public 특성을 가지고 있기 때문에 생략하더라도 자동적으로 컴파일 과정에서 붙게 된다.

  • 정적 메소드  : 객체가 없어도 인터페이스 만으로 호출이 가능한 메서드이다. 형태는 클래스의 정적 메서드와 정말 동일하다.

2. 인터페이스 구현

개발코드가 인터페이스 메서드를 메서드를 호출하면 인터페이스는 객체의 메서드를 호출한다. 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메서드 이름, 매개 타입, 리턴 타입을 가진 실체 메서드를 가지고 있어야 한다. 이러한 객체를 인터페이스의 구현 객체라고 하고 구현 객체를 생성하는 클래스가 바로 구현 클래스이다.

💡 구현 클래스 선언 예

public class 구현클래스명 implements 인터페이스명 {
   // 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}

구현 클래스에서 인터페이스 추상 메소들에 대한 실체 메서드를 작성할 때 주의할 점은 public 보다 더 낮은 접근 제한으로 작성할 수 없다. 만약 인터페이스에 선언된 추상 메서드에 대응하는 실체 메서드를 구현 클래스가 작성하지 않으면 구현 클래스는 자동적으로 추상 클래스가 되어버린다. 그렇기 때문에 구현 클래스 선언부에는 꼭 abstract 키워드를 추가해야 한다. 구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있다. 인터페이스로 구현 객체를 사용하려면 인터페이스 변수를 선언하고 구현 객체를 대입해야 한다. 인터페이스 변수는 참조 타입이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.

💡 인터페이스 변수에 구현 객체 대입의 예

public class RemoteExample {
  public static void main(String[] args) {
      Remote re;
      re = new TV();
      re = new Audio();
  }
}

2-1. 다중 인터페이스 구현 

다중 인터페이스를 구현할 경우, 구현 클래스는 모든 인터페이스의 추상 메서드에 대해 실체 메서드를 작성해야 한다. 만약 하나라도 없으면 추상 클래스로 선언해야 한다.

public class 구현클래스명 implements 인터페이스A, 인터페이스B {
    // 인터페이스 A에 선언된 추상 메소드의 실체 메소드 선언
    // 인터페이스 B에 선언된 추상 메소드의 실체 메소드 선언
}

3. 익명 구현 객체

자바는 소스 파일을 만들지 않고 구현 객체를 만들 수 있는 방법을 제공하는데 그것이 바로 익명 구현 객체이다.  필드와 메소드를 선언할 수 있지만, 익명 객체 안에서만 사용할 수 있고 인터페이스 변수로 접근할 수 없다.

💡 익명 구현 객체 선언 방법 예

인터페이스명 변수 = new 인터페이스명() {
    // 인터페이스에 선언된 추상 메소드의 실체 메소드 선언
}

4. 자동 타입 변환(Promotion)

구현 객체가 인터페이스 타입으로 변환되는 것이 자동 타입 변환이다. 인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환시킬 수 있다.

5. 인터페이스 배열로 구현 객체 관리

💡 배열로 구현 객체 관리 방법 예

Tire[] tires = {
   new ATire(),
   new ATire(),
   new ATire(),
   new ATire()
};

6. 강제 타입 변환(Casting)

구현 클래스에 선언된 필드와 메소드를 사용해야 할 경우 강제 타입 변환을 해서 다시 구현 클래스 타입으로 변환한 후 구현 클래스의 필드와 메소드를 사용할 수 있다.

7. 인터페이스의 상속

인터페이스도 다른 인터페이스를 상속할 수 있다. 클래스와는 달리 다중 상속을 허용하며 extends 키워드 뒤에 여러 개 나열할 수 있다. 하위 인터페이스를 구현하는 클래스는 하위 인터페이스의 메서드뿐만 아니라 상위 인터페이스의 모든 추상 메소드에 대한 실체 메서드를 가지고 있어야 한다. 그렇기 때문에 구현 클래스로부터 객체를 생성하고 난 후 하위 및 상위 인터페이스  타입으로 변환이 가능하다. 상위 인터페이스로 타입 변환되면 상위 인터페이스에 선언된 메서드만 사용 가능하고 하위 인터페이스에 선언된 메서드는 사용할 수 없다.

 

📌 확인 문제 답 

  • 3번 문제

// Cat.java
package question3;
public class Cat implements Soundable {
	public String sound() {
		String cat = "야옹";
		return cat;
	}
}

// Dog.java
package question3;
public class Dog implements Soundable {
	public String sound() {
		String dog = "멍멍";
		return dog;
	}
}
  • 4번 문제
// DataAccessObject 인터페이스
public interface DataAccessObject {
     void select();
     void insert();
     void delete();
     void update();
}


// OracleDao.java
public class OracleDao implements DataAccessObject {

	@Override
	public void select() {
		System.out.println("Oracle DB에서 검색");
	}

	@Override
	public void insert() {
		System.out.println("Oracle DB에서 삽입");
	}

	@Override
	public void delete() {
		System.out.println("Oracle DB에서 삭제");
	}

	@Override
	public void update() {
		System.out.println("Oracle DB에서 수정");
	}

}


// MySqlDao.java
public class MySqlDao implements DataAccessObject {

	@Override
	public void select() {
		System.out.println("MySql DB에서 검색");
	}

	@Override
	public void insert() {
		System.out.println("MySql DB에서 삽입");
	}

	@Override
	public void delete() {
		System.out.println("MySql DB에서 삭제");
	}

	@Override
	public void update() {
		System.out.println("MySql DB에서 수정");
	}

}
  • 5번 문제

public class ActionExample {

	public static void main(String[] args) {
		Action action = new Action() {
			@Override
			public void work() {
               System.out.println("복사를 합니다.");				
			}
		};
		action.work();
	}
}