언어/JAVA

[JAVA] Interface

hvoon 2022. 9. 8. 11:24

자바언어에서 제공하는 상속 기능은  일반 클래스이든, 추상클래스이든 단일 상속만을 지원함. 하나의 클래스는 하나의 부모클래스를 가질 수 있음(여러개의 클래스를 상속할 수 없음).
- class SubA extends SuperA, SuperB {} -> 에러

다중 상속을 위해 만들어진  interface
-인터페이스는 제약이 다소 있는 클래스

- 추상클래스보다도 더 상속을 위해서 만들어진 클래스.  다중 상속이 가능.

- class 만들듯이 생성하며, class란 키워드 대신 interface 라는 키워드를 써서 생성
1. 인터페이스는 멤버필드(변수)로 public static final 멤버만 가질 수 있음
2. 추상클래스처럼 일반 멤버변수와 일반 멤버 메서드를 가질 수 없음
3. 인터페이스는 멤버메소드로 public abstract 메서드만 가질 수 있음

interface InterA {
	int n1 = 10;   // public static final int n1 = 10; 이라고 쓴것과 같음 
	// public static final 라는 키워들이 생략된 상태
	
	// 인터페이스에는 일반 멤버변수를 만들수 없으며, 위와 같이 단순 멤버변수를 만들어도
	// static final 로 인식되서 굵은 남색으로 표시됨
	// static final 변수는 변수 생성시 반드시 값을 초기화해줘야 함
	
	// InterA(){}   // 에러... 인터페이스는 생성자를 갖을수 없음
	// 생성자는 일반클래스와 추상클래스만 만들수 있음
	
	// public void print() {}  // 에러... 일반 멤버메서드도 선언이 불가함.
	
	// 인터페이스 내부에 선언할 수 있는 요소
	public static final int num = 10;
	public abstract void test1();
	public void test2();  //  abstract 가 생략된 상태이며, 자동으로 추상메서드로 인식됨
}

// 인터페이스를 상속(구현)하는 클래스는 상속(구현)할 클래스 앞에 extends 대신 implements를 씀
class SubA implements InterA{
	@Override
	public void test1() {
		System.out.println("SubA 클래스의 test1 메소드 실행");
	}
	@Override
	public void test2() {
		System.out.println("SubA 클래스의 test2 메소드 실행");
	}
}

public class Interface01 {
	public static void main(String[] args) {
		// 인터페이스는 객체를 생성할 수 없음.
		// 1. 추상메소드를 포함할 수 있기때문에...		
		// InterA a = new InterA(); // 에러
		
		// 상속을 통한 다형성 구현에만 인터페이스가 활용됨
		// 부모 인터페이스의 레퍼런스를 사용하여 자식 클래스의 객체를 참조 가능
		InterA a = new SubA();
		// 부모 인터페이스의 레퍼런스를 사용하여 자식 클래스의 오버라이딩된 메소드를 호출
		a.test1();
		a.test2();
		// 자식 인스턴스를 전달인수로 보내고, 부모인터페이스의 레퍼런스를 매개변수로하여 사용 가능
		test(a);
	}
	public static void test(InterA a) {}
}
// 인터페이스들의 생성
interface InterSuper1{
	public abstract void interSuper1Method();
}
interface InterSuper2{
	public abstract void interSuper2Method();
}

// 인터페이스들끼리의 상속(extends): 
// 인터페이스를 인터페이스가 상속할 때는  implements를 쓰지않고 extends를 씀.
// 인터페이스끼리는 다중상속(extends)가 가능
interface InterSub extends InterSuper1, InterSuper2{
	public abstract void interSubMethod();
	// public abstract void interSuper1Method();  상속받은 추상메서드
	// public abstract void interSuper2Method();  상속받은 추상메서드
}   
// 인터페이스끼리의  extends 는 추상메서드들을 온전히 물려받은 것만으로 마무리하고,
// 추상매서드의 override 의무는 면제됨

// 일반 클래스가 인터페이스를 다수개 implements 했다면 그 인터페이스 들이
// 보유한 추상메서들을 모두 구현(override, implements)해야함
class ClassSub1 implements InterSuper1, InterSuper2{
	@Override
	public void interSuper2Method() {
		System.out.println("interSuper2Method 메서드 입니다");
	}
	@Override
	public void interSuper1Method() {
		System.out.println("interSuper1Method 메서드 입니다");
	}	
}

// 인터페이스 간 상속(extends)이 이루어져 있는 인터페이스를 클래스에서 구현(implements)하는 경우 
// 부모 인터페이스의 추상메소드를 포함하여 모두 오버라이딩해야함
class ClassSub2 implements InterSub {
	@Override
	public void interSuper1Method() {		
		System.out.println("interSuper1Method 메서드 입니다");
	}
	@Override
	public void interSuper2Method() {
		System.out.println("interSuper2Method 메서드 입니다");
	}
	@Override
	public void interSubMethod() {
		System.out.println("InterSubMethod 메서드 입니다");
	}
}

public class Interface02 {
	public static void main(String[] args) {
		// 자식 레퍼런스 = 자식 인스턴스
		ClassSub1 cs1 = new ClassSub1();
		ClassSub2 cs2 = new ClassSub2();
		
		// 부모 레퍼런스 = 자식 인스턴스
		// 구현(implements)관계가 있는 부모자식간에만 대입이 가능
		InterSuper1 is1 = new ClassSub1();  // 가능
		InterSuper2 is2 = new ClassSub1();  // 가능
		
		InterSuper1 is3 = new ClassSub2();  // 가능
		InterSuper2 is4 = new ClassSub2();  // 가능
		
		// InterSub is5 = new ClassSub1();  // 불가능 - 에러
		InterSub is6 = new ClassSub2();  // 가능
		
        
		// 상속되고 구현된 메서드만 사용이 가능
		cs1.interSuper1Method();   // 가능
		cs1.interSuper2Method();   // 가능
		// cs1.interSubMethod();  // 에러
		
		cs2.interSuper1Method();   // 가능
		cs2.interSuper2Method();   // 가능
		cs2.interSubMethod();  // 가능
		
		is1.interSuper1Method();   // 가능
		//is1.interSuper2Method();   // 불가능
		//is1.interSubMethod();  // 불가능
		
		//is2.interSuper1Method();   // 불가능
		is2.interSuper2Method();   // 가능
		//is2.interSubMethod();  // 불가능
		
		is3.interSuper1Method();   // 가능
		//is3.interSuper2Method();   // 불가능
		//is3.interSubMethod();  // 불가능	
		
		//is4.interSuper1Method();   // 불가능
		is4.interSuper2Method();   // 가능
		//is4.interSubMethod();  // 불가능	
		
		is6.interSuper1Method();   // 가능
		is6.interSuper2Method();   // 가능
		is6.interSubMethod();  // 가능		
	}
}
abstract class Unit{
	// 모든 캐릭터가 갖는 공통요소
	private int hp;  // 현재 체력
	private int max_hp;  // 최대 체력
	Unit(int p){
		max_hp = p;       // 각 캐릭터 마다 다른 전달값으로 최대 체력과 현재 체력을 설정
		hp = (int)(p*0.8);
	}
	public abstract void move( int x, int y);
	//{
	//	System.out.println("x:" + x + ", y:" + y + "로 이동합니다");
	//}
}
class GroundUnit extends Unit{
	// GroundUnit 만의 특정요소
	GroundUnit(int p){
		super(p);
	}
	@Override
	public void move(int x, int y) {
		System.out.println("x:" + x + ", y:" + y + "로 뛰어갑니다");
	}
}
class AirUnit extends Unit{
	// AirUnit 만의 특정요소
	AirUnit(int p){
		super(p);
	}
	@Override
	public void move(int x, int y) {
		System.out.println("x:" + x + ", y:" + y + "로 날아갑니다");
	}
}
class Tank extends GroundUnit implements Repairable{
	Tank(){
		super(150);
		// max_hp = 150;  // 에러
	}
	public String toString() {  
		return "Tank"; 
	}
}
class Dropship extends AirUnit implements Repairable{
	Dropship(){
		super(120);
	}
	public String toString() {  
		return "Dropship"; 
	}
}
class Marine extends GroundUnit{
	Marine(){ super(40); }
	public String toString() { return "Marine"; }
}
class SCV extends GroundUnit implements Repairable{
	SCV(){	 super(40); }
	public String toString() { return "SCV"; }
	
	//public void repaire( Tank t) {}
	//public void repaire( Dropship d) {}
	// public void repaire( Marine m) {}
	public void repaire( Repairable r ) {
		if( r instanceof Unit) {
			Unit u = (Unit)r;
		}
	}
}

interface Repairable {
}

public class Interface03 {
	public static void main(String[] args) {
		Tank t = new Tank();
		Dropship d = new Dropship();
		Marine m = new Marine();
		SCV s1 = new SCV();
		
		s1.repaire(t);  
		s1.repaire(d);
		// s1.repaire(m);   // 치료 불가
	}
}