KH/JAVA

# 25 Interface (인터페이스)

오늘의 진 2022. 7. 19. 12:46

Interface (인터페이스)

 

인터페이스란?

 

-자바는 클래스를 사용하는 객체지향 프로그래밍 언어이다.

클래스는 생성자, 변수, 메소드로 구성되어 있고 다중 정의와 재정의, 추상 클래스, 추상 메서드, 종단 클래스 등 

다양한 문법을 갖고 있지만 단일 상속만을 고려하여 만들어졌기 때문에 확장성에 문제가 있다.

이러한 문제를 보와한 것이 인터페이스이다.

 

-인터페이스도 클래스와 마찬가지로 자바의 중요한 구성 요소이다.

인터페이스는 상수와 몸통이 없는 메소드로 구성된다.

즉 추상 메소드와 상수만으로 구성된 것이 인터페이스이다.

자바는 많은 인터페이스를 제공한다. 윈도우 프로그램, JDBC, 네트워크, Tread 등에서 많이 사용된다.

 

인터페이스와 추상 클래스의 차이점

인터페이스 추상클래스
다중상속 가능 단일상속가능
모든메소드가 추상메소드이다. 한개이상의 추상메소드를 갖는다.
interface 키워드를사용 abstract 키워드를 사용
상속받을때 implements(구현한다는 의미) 키워드사용 상속받을때 extends 키워드 사용
인터페이스에 있는 모든 메소드가 추상메소드이기 때문에     메소드 앞에 abstract 키워드를 따로 붙이지 않는다. 추상메소드 앞에는 abstract가 붙는다.

 

< 인터페이스 사용방법 >

public interface 인터페이스 이름 [extends 인터페이스 2 ,,,,,,(인터페이스가 인터페이스를 상속받을 때 여러 개 가능)  ]
{
         .......  ;   // 상수 선언
        ................ ;   // 이름만 있는 메서드 선언
}

 

자바에서 추상 클래스와 유사한 인터페이스를 만든 이유

 

1. 단일 상속의 한계를 보완한다.

  :  클래스는 단일 상속만 가능하기 때문에 클래스의 확장성, 재사용성에 한계가 있다. 

     하지만 인터페이스는 다중 상속이 가능하기 때문에 단일 상속의 문제를 어느 정도 보완할 수 있다.

 

2. 클래스 명세표를 만든다.

  : 인터페이스는 내용이 없는 메서드로 구성되기 때문에 인터페이스를 상속받는 클래스는 

    반드시 메서드를 재정의해(오버라이딩하여) 사용한다.

 

 

<  인터페이스의 상속 > 

 

인터페이스 사이의 상속 ( 인터페이스와 인터페이스 사이에서는 extends 사용 , 다중상속 가능 )

public interface  인터페이스 이름   extends  인터페이스 이름 ,,,
{
             ....... ;   // 상수
             ............. ;   // 메소드
}

 

클래스에서의 구현 ( 클래스와 인터페이스 사이에서는 implements 사용, 다중상속 가능 )

public class   클래스 이름  implements 인터페이스 이름 ,,,

                ...... ;   // 멤버
               ............... ;  // 구현 메소드
}

 

 

 

(예시)

interface AA_1 {
	void print1(); // 추상메소드
	// public abstract void print1(); 이라는의미
}

class BB_1 implements AA_1 {

	@Override
	public void print1() {
		System.out.println("AA_1 인터페이스 메소드 재정의");
	}

	public void print2() { // BB의 자체 메소드
		System.out.println("BB_1 클래스 메소드 print2()");
	}

}

public class InterfaceTest_1 {
	public static void main(String[] args) {

		BB_1 obj_1 = new BB_1();

		obj_1.print1();
		obj_1.print2();

		System.out.println("\n================================\n");

		AA_1 obj_2 = new BB_1();

		obj_2.print1();
		// obj_2.print2(); BB의 자체 매소드는 사용 불가
		// 오버라이딩이 된 메소드만 실행가능하다. BB의 것 실행됨

	}

}

 

 

 

 

 

 

 

 

 

(예시) - Interface 에서의 변수

interface AA_2 {
	int kbs = 999; // static final int kbs = 999; 라는뜻
	// interface 안의 맴버 변수는 상수이다(값 변경 불가). 관례상 대문자로 쓴다.
}

class BB_2 implements AA_2 {

	int kbs = 789;
	int mbc = 345;
}

public class InterfaceTest_2 {
	public static void main(String[] args) {

		BB_2 obj_1 = new BB_2();

		obj_1.kbs = 111; // BB_2의 것
		obj_1.mbc = 333;

		// AA_2.kbs = 345; 상수이기 때문에 값 변경 불가능

		System.out.println("kbs 11 = " + obj_1.kbs);
		// BB에 kbs가 있다면 BB의 것이 출력된다. 없다면 AA의 것이 출력됨
		System.out.println("kbs 22 = " + AA_2.kbs); // kbs는 스테틱이므로 class명으로 접근가능
		System.out.println("mbc  = " + obj_1.mbc);
	}
}
kbs 11 = 111
kbs 22 = 999
mbc = 333

static 으로 선언된 AA의 kbs는  메소드 영역에 만들어지고

BB의 kbs , mbc는 힙영역에 만들어짐  , stack  영역에 주소값을 담을 obj_1 만들어짐

두개의 kbs는 만들어지는 위치가 다른 서로 다른 객체이다. 

 

 

 

(예시) - 매개변수로써의 class

interface Mbc {
	void play();

}

class Kbs {
	void autoPlay(Mbc obj) {
		obj.play();
	}
}

class MySbs implements Mbc {

	@Override
	public void play() {
		System.out.println("MySbs TV 생방송 ###");
	}

}

class MyCNN implements Mbc {

	@Override
	public void play() {
		System.out.println("MyCNN TV 야구생중계 @@@");
	}

}

public class InterfaceTest_3 {
	public static void main(String[] args) {

		Kbs obj = new Kbs();

		obj.autoPlay(new MySbs()); // new MySbs 해서 객체를 만들어서 autoPlay의 매개변수로 전달해줌
		obj.autoPlay(new MyCNN());
		// Mbc를 상속받은 MySbs , MyCNN 이므로 (Mbc obj)로 전달가능
		// 즉, 상속받은 친구들이므로 Mbc로 자동형변환이 가능하기 때문

	}

}

 

 

 

   (Mbc obj) 가들어올자리 즉, Mbc obj  = new Mbc(); 인 Mbc의 인스턴스들이들어오는 자리인데 MySbs , MyCNN은 Mbc를 상속받은 클래스들이므로 new MySbs , new MyCNN 을 해준 친구들은 MBC로 자동 형변환이 되어 MBC의 인스턴스가  들어오는 자리인  (Mbc obj) 자리에 들어갈수 있다. 

 

 

 

 

 

(예시) - Interface 의 다중상속

interface Bird {
	long speed = 65; // static final 생략

	void fly(); // public abstract 생략
}

interface Horse {
	void run();
}

interface Fish {
	void swimming();
}

class Pefasus implements Bird, Horse, Fish { // 인터페이스는 다중상속 가능

	@Override
	public void swimming() {
		System.out.println("바다를 헤엄친다 ~~~");
	}

	@Override
	public void run() {
		System.out.println("대륙을 뛰어다닌다 @@@");
	}

	@Override
	public void fly() {
		System.out.println("푸른 하늘을 날아다닌다 ###");
	}
}

public class PefasusTest {
	public static void main(String[] args) {

		Pefasus obj = new Pefasus();

		obj.fly();
		System.out.println("속도는 : " + Bird.speed + "입니다."); // static 이므로 클래스명으로 접근

		obj.run();
		obj.swimming();

		System.out.println();
		
		Bird obj2 = new Pefasus();

		obj2.fly();
		System.out.println("속도는 : " + Bird.speed + "입니다."); 
		//obj2.run();   Bird에 존재하지 않음으로 사용 불가능
		//obj2.swimming();

	}

}

 

 

 

 

 

 

 

 

 

(예제) - 인터페이스 사이의 상속

interface Car {
	void run();
}

interface Ship {
	void navigate();
}

interface Mole {
	void dig();
}

interface Wigs extends Car, Ship, Mole {
	// 인터페이스가 인터페이스를 상속받을때 다중상속이가능하다.
	// 또한 이때는 extends를 이용
	void floating();
}

class EagelFive implements Wigs  { // 클래스가 인터페이스를 상속 받을때는 implement이용(다중상속 가능)

	@Override
	public void run() {
		System.out.println("황야를 달린다 !!!");
	}

	@Override
	public void navigate() {
		System.out.println("바다를 질주한다 @@@");
	}

	@Override
	public void floating() {
		System.out.println("습지를 날아다닌다 ###");
	}

	@Override
	public void dig() {
		System.out.println("땅속을 파고 다닌다 ~~~");
	}

}

public class WigsTest {
	public static void main(String[] args) {

		EagelFive obj = new EagelFive();

		obj.floating();
		obj.run();
		obj.navigate();
		obj.dig();

	}
}