관리 메뉴

나구리의 개발공부기록

자바의 정석 기초편 ch7 - 35 ~ 38 [인터페이스의 선언, 상속, 구현, 인터페이스와 다형성] 본문

유튜브 공부/JAVA의 정석 기초편(유튜브)

자바의 정석 기초편 ch7 - 35 ~ 38 [인터페이스의 선언, 상속, 구현, 인터페이스와 다형성]

소소한나구리 2023. 11. 29. 16:44

1) 인터페이스(interface)

  • 추상 메서드의 집합(프로그래밍 관점)즉 구현된 것이 전혀 없는 설계도(껍데기)
  • 추상메서드가 인터페이스의 핵심이며 static메서드, 상수, 디폴트메서드(접근제어자가 아님)는 부수적인 요소임 
  • 모든멤버는 public 접근제어자가 기본임

(1) 추상클래스와 인터페이스의 차이

  • 추상클래스 -> 일반클래스인데 추상메서드를 가지고 있음 즉 iv나, 생성자들이 있을 수 있음
  • 인터페이스 -> 아무것도 없고 추상메서드만 가지고있으며 iv를 가질 수 없음, 일반 메서드를 가질 수 있도록 변경되었긴 여전히 iv는 없고 다중상속이 가능함

(2) 예제

  • interface에서 제어자 없이 그냥 변수를 선언하면 항상 public, static, final 제어자가 기본값이므로 상수로 선언됨
  • 제어자 없이 메서드를 선언하여도 public, abstract 제어자가 기본값이므로 자동으로 추상 메서드가 됨
interface 인터페이스이름 {
	public static final 타입 상수이름 = 값;	// 상수
	public abstract 메서드이름(매개변수목록);	  // 추상메서드
	// 변수 불가
	// 모든 멤버는 public
}

// 이름이 PlayingCard라는 인터페이스 생성
interface PlayingCard {

	// 인터페이스의 모든 상수들은 public,static,final을 전부 or 일부 생략 가능
	// 항상 public static final임
	public static final int SPADE = 4;
	final int DIAMOND = 3;
	static int HEART = 2;
	int CLOVER = 1; 	// 변수처럼보여도 상수임
    
	// 인터페이스의 모든 메서드들은 public, abstract를 전부 or 일부 생략 가능
	// 항상 public abstract임
	public abstract String getCardNumber();
	String getCardKind();

}

 

2) 인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능하며 클래스가 아니므로 Object클래스가 최고 조상이 아님
  • 다중 상속이 가능함 (조상이 여러개  - 추상메서드는 충돌해도 문제 없음)
  • 자바에서 단일상속을 원칙으로 설계했던 이유는 메서드의 구현부가 달랐기 때문인데 메서드가 선언부만 있으므로 충돌이 없음
// 2개의 인터페이스의 멤버를 다중 상속 - OK
interface Fightable extends Movable, Attackable { } 
	// 멤버가 2개 - Movable, Attackable의 메서드 각 1개씩 상속
    
interface Movable{
	void move(int x, int y);
}

interface Attackable {
	void attack(unit u);
}

 

3) 인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성 클래스에 구현하여(implements) 완성하는 것 -> 클래스 상속과 비슷한 메커니즘
  • 일부만 구현하는 경우 클래스 앞에 abstract를 붙혀야 함 -> 추상클래스와 동일한 메커니즘
class 클래스이름 implements 인터페이스이름 {
	// 인터페이스의 정의된 추상메서드들을 모두 구현
}

interface Fightable {	// Fightable 인터페이스
	void move(int x, int y);    // 추상메서드(public abstract 생략됨)
	void attack(unit u);	    // 추상메서드
}


// 	Fighter 인터페이스가 Fightable 인터페이스를 구현 함
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) { /* 내용생략 */ }
//	public abstract void attack(Unit u); 가 생략 되어있음
}

4) QnA

Q.인터페이스란?

  • A. 추상 메서드의 집합
  • 상수, static메서드, 디폴트메서드는 JDK 1.8(Java 8) 부터 추가됨

Q.인터페이스의 구현이란?

  • A. 인터페이스의 추상메서드의 구현부를 만들어서 재정의 하는 것 (미완성 설계도를 완성)

Q.인터페이스와 추상클래스의 공통점은?

  • A. 추상 메서드를 가지고 있다는 것

Q.인터페이스와 추상클래스의 차이점은?

  • A. 인터페이스는 iv를 가질 수 없음
  • 추상클래스는 클래스의 상속을 통해 메서드를 완성하지만 인터페이스는 구현(implements)를 통해 메서드를 완성
  • 인터페이스는 다중 상속이 가능함

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

  • 인터페이스도 구현클래스의 부모임
  • 인터페이스 타입 매개변수는 인터페이스를 구현한 클래스의 객체만 가능
  • 메서드의 매개변수가 인터페이스타입이면 인터페이스를 구현한 클래스의 인스턴스(객체)를 메서드 호출 시 인자로 입력할 수 있음
  • 인터페이스를 메서드의 리턴타입(반환타입)으로 지정할 수 있으며 인터페이스를 구현한 클래스의 인스턴스(객체)를 반환함

(1) 예제1

  • 인터페이스의 다형성을 이용한 구현
  • 반환타입의 인터페이스를 구현한 클래스들의 객체를 생성하는 코드를 재활용 하는 반환타입이 인터페이스인 method()를 정의
public class InterfaceTest2 {
    public static void main(String[] args) {
        Unit u = new Fighter();	// Ok
        Fightable f = new Fighter();	// OK 단, Fightable에 선언된 메서드만 사용 가능!
        Fightable f2 = method();	// 위의 코드와 동일함(method();가 new Fighter();를 반환)

        f.move(100,200);
        f.attack(new Fighter());
    }
    static Fightable method() {	// 반환타입이 인터페이스
        // Fighter 객체를 반환 (Figthable을 구현한 클래스의 객체)
        // 타입이 일치하지 않지만 다형성때문에 가능함
        // 원래는 return Fightable f;로 반환해야 하지만 (Fightable)이 생략됨 -> 자동형변환
        Fightable f = new Fighter();
        return f;
    //	return new Fighter(); 위 2문장을 한번에 작성할 수도 있음
    }
}
// Fighter 클래스는 Unit클래스를 상속받고 Fightable 인터페이스를 구현 (다중 상속)
// Unit, Fightable 모두 조상이 됨 -> 다형성 가능
class Fighter extends Unit implements Fightable {
    public void move(int x, int y) { /* 내용생략 */ }
    public void attack(Fightable f) { /* 내용생략 */ }
}

interface Fightable {	        // Fightable 인터페이스
    void move(int x, int y);	// 추상메서드(public abstract 생략됨)
    void attack(Fightable f);	// 매개변수가 인터페이스
}
class Unit {	// Unit 클래스
    public void stop() { /* 내용생략 */ }
}

 

(2) 예제 2

  • 메서드 오버라이딩 시 조상의 접근 제어자보다 범위가 좁으면 안됨
abstract class Unit2 {	// 추상클래스
	int x, y;
	abstract void move(int x, int y);
	void stop() {System.out.println("스탑!"); }
}

interface Fightable {	// 인터페이스
	void move(int x, int y);	// public abstract가 생략
	void attack(Fightable f);	// 위와동일
}

class Fighter extends Unit2 implements Fightable {
	// 오버라이딩 규칭 : 조상보다 접근 제어자가 좁으면 안됨 
	// 조상의 접근제어자 - public (인터페이스의 오버로딩은 모두 public 붙혀야 됨)
	public void move(int x, int y) {
		System.out.println("["+x+","+y+"]로 이동");
	}
	public void attack(Fightable f) {
		System.out.println(f+" 공격");
	}
}

public class FighterTest {

	public static void main(String[] args) {
		
		Fighter f = new Fighter();
//		Fighter(Unit2를 상속받고 Fightable을 구현한 클래스) 리모콘 사용 - 모두 사용가능
		f.move(100, 200);
		f.attack(new Fighter());
		f.stop();
		
//		Unit2(부모클래스) 리모콘 사용 - 구현메서드 사용 불가
		Unit2 u = new Fighter();
		u.move(100, 200);
		u.stop();
//		u.attack(new Fighter()); 에러 / attack() 호출불가 - Unit2에 없음
		
		
//		Fightable(인터페이스) 리모콘 사용 - 상속받은 메서드 사용 불가
		Fightable f2 = new Fighter();	//
		f2.move(100, 200);
		f2.attack(new Fighter());
//		f2.stop();	에러 / stop()호출불가 Fightable에 없음
	}
}

 

** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의