Hello

Java 인터페이스와 다형성

by 볼빵빵오춘기

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

  • 인터페이스도 구현 클래스의 부모라 표현이 가능한건가? yes
더보기

⇒ 인터페이스는 아예 내용이 없으니 충돌이 나는것을 막으면서도 다중상속의 효과를 낸다.

더보기
class Fighter extends Unit implements Fightable{
	public void move(int x, int y){ /* 내용생략 */ }
	public void attack(Fightable f){ /* 내용생략 */ }
}

class Unit{
	/* 내용 생략 */
	move(int x, int y){
		/* 내용 생략 */
	}
	/* 내용 생략 */
}

interface Fightable{
	void move(int x, int y);
	void attrack(Fighter f);
}

Fighter은 Unit을 상속받고 Fightable을 인터페이스로 구현했다.

따라서 단일상속만 허락하는 자바에서 위에 같이 씀으로 다중상속의 효과를 낸다.

그렇기 때문에

Unit u = new Fighter();
Fightable f = new Fighter();

위에 코드와 같이 형 변환이 가능하고

만약 Fightable로 형변환했다면

Fightable 메서드인 move(int x, int y), attrack(Fighter f) 밖에 사용하지 못한다.

  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
더보기

⇒ 즉 Fightable을 인터페이스 한 객체만 사용이 가능하다는 의미(위의 더보기 참고)

interface Fightable{
	void move(int x, int y);
	void attack(Fighter f);
}

여기서 attrack(Fighter f); 메서드를 보면 매개변수가 인터페이스인 Fightable이다.

이처럼 매개변수가 인터페이스로 올 경우에는

매개변수로 온 인터페이스로 구현한 객체만 사용이 가능하다.

  • 인터페이스를 메서드의 리턴타입으로 지정할 수 있다.
더보기

⇒ 반환타입이 일치하진 않지만 다형성 때문에 가능.

반환타입이 인터페이스란 의미는 이 인터페이스 구현한 놈을 반환한다는 의미

더보기
Fightable method(){
	/*내용생략*/
}

선언부에 method()의 반환타입은 Fightable이다.

이럴 경우 Fightable인터페이스를 구현한 클래스의 인스턴스를 반환해야한다.

 

예제

  • 예제2, 3, 4는 예제1과 비교해서 보기!
  • 예제2, 3, 4는 객체의 형변환시 쓸 수 있는 메서드를 보여주기위함의 예제이다.
  • 예제5는 타입이 일치해야함을 보여주기위함의 예제이다.

예제1

더보기
abstract class Unit{
	int x, y;
	abstract void move(int x, int y);
	void stop() { System.out.println("stop!!!"); }
}

interface Fightable{ // 인터페이스의 모든 메서드는 public abstract. 예외없음
	void move(int x, int y); // public abstract가 생략됨	
	void attack(Fightable f);  // public abstract가 생략됨
}

class Fighter extends Unit implements Fightable{
	 // 오버라이딩 규칙 : 조상보다 접근어자가 좁으면 안된다.
	// 위에 public이 없더도 붙여줘야한다. 
	// 여기서 접근제어자 생략 실수위험도가 높다.
	public void move(int x, int y) {
		System.out.println("[x="+x+", y="+y+"]이동 ");
	};	
	public void attack(Fightable f) {
		System.out.println(f+"를 공격 ");
	};
}



public class FighterTest {

	public static void main(String[] args) {
		Fighter f = new Fighter();
		f.move(100,200);
		f.attack(new Fighter());
	}

}

예제2

더보기
abstract class Unit{
	int x, y;
	abstract void move(int x, int y);
	void stop() { System.out.println("stop!!!"); }
}

interface Fightable{ // 인터페이스의 모든 메서드는 public abstract. 예외없음
	void move(int x, int y); // public abstract가 생략됨	
	void attack(Fightable f);  // public abstract가 생략됨
}

class Fighter extends Unit implements Fightable{
	 // 오버라이딩 규칙 : 조상보다 접근어자가 좁으면 안된다.
	// 위에 public이 없더도 붙여줘야한다. 
	// 여기서 접근제어자 생략 실수위험도가 높다.
	public void move(int x, int y) {
		System.out.println("[x="+x+", y="+y+"]이동 ");
	};	
	public void attack(Fightable f) {
		System.out.println(f+"를 공격 ");
	};
}

public class FighterTest {

	public static void main(String[] args) {
		Unit f = new Fighter(); // => 타입을 Fighter에서 Unit으로 변경함.
		f.move(100,200);
		f.attack(new Fighter());
	}

}

⇒ Unit에는 attack(Fightable f)메소드가 없어서 에러가남

예제3

더보기
abstract class Unit{
	int x, y;
	abstract void move(int x, int y);
	void stop() { System.out.println("stop!!!"); }
}

interface Fightable{ // 인터페이스의 모든 메서드는 public abstract. 예외없음
	void move(int x, int y); // public abstract가 생략됨	
	void attack(Fightable f);  // public abstract가 생략됨
}

class Fighter extends Unit implements Fightable{
	 // 오버라이딩 규칙 : 조상보다 접근어자가 좁으면 안된다.
	// 위에 public이 없더도 붙여줘야한다. 
	// 여기서 접근제어자 생략 실수위험도가 높다.
	public void move(int x, int y) {
		System.out.println("[x="+x+", y="+y+"]이동 ");
	};	
	public void attack(Fightable f) {
		System.out.println(f+"를 공격 ");
	};
}

public class FighterTest {

	public static void main(String[] args) {
		Fightable f = new Fighter(); // Fighter이었던 타입을 Fightable으로 변경
		f.move(100,200);
		f.attack(new Fighter());
	}

}

예제4

더보기
public class FighterTest {

	public static void main(String[] args) {
		Unit u = new Fighter();
		u.move(100,200);
		u.attack(new Fighter()); // Unit에는 attact()이 없어서 호출불가 
		u.stop();
		
		Fightable f = new Fighter();
		f.move(100,200);
		f.attack(new Fighter());
		f.stop(); // Fighter에는 stop()이 없어서 호출불가 
	}

}

에러남

⇒ Unit에는 attact()이 없어서 호출불가

⇒ Fighter에는 stop()이 없어서 호출불가

예제5

더보기
abstract class Unit{
	int x, y;
	abstract void move(int x, int y);
	void stop() { System.out.println("stop!!!"); }
}

interface Fightable{ // 인터페이스의 모든 메서드는 public abstract. 예외없음
	void move(int x, int y); // public abstract가 생략됨	
	void attack(Fightable f);  // public abstract가 생략됨
}

class Fighter extends Unit implements Fightable{
	 // 오버라이딩 규칙 : 조상보다 접근어자가 좁으면 안된다.
	// 위에 public이 없더도 붙여줘야한다. 여기서 접근제어자 생략 실수위험도가 높다
	public void move(int x, int y) {
		System.out.println("[x="+x+", y="+y+"]이동 ");
	};	
	public void attack(Fightable f) {
		System.out.println(f+"를 공격 ");
	};

	// 추가 부분 start
	// 싸울 수 있는 상대를 불러온다.
	Fightable getFightable(){ // =>>>>>> 여기의 타입!!!!!!
		Fighter f = new Fighter(); // Fighter를 생성해서 반환
		return f; // =>>>>>> 여기의 타입!!!!!!
	}
	// 추가 부분 end

}

public class FighterTest {

	public static void main(String[] args) {
		Fighter f = new Fighter();
		Frghtable f2 = f.getFightable(); // =>>>>>> 여기의 타입!!!!!! 
	}

}

⇒ 코드에서 // =>>>>>> 여기의 타입!!!!!! ⇒ 타입이 일치해야함을 보여주기위함.

 

 

블로그의 정보

Hello 춘기's world

볼빵빵오춘기

활동하기