[Java] 자바 Generic(제네릭) 상속과 인터페이스 살펴보기!

2020-12-20


제네릭 타입의 클래스와 인터페이스에서도 상속과 구현이 가능하다. 구체적인 예를 들면서 살펴보자.


우선 제네릭 타입의 클래스 간의 상속관계를 알아보자.

package GenericExtends;

public class Parent <A,B> {
	//제넥릭타입 A/B를 가지는 Parent 클래스
	private A name;
	private B age;
	
	public A getName() {
		return name;
	}
	public void setName(A name) {
		this.name = name;
	}
	public B getAge() {
		return age;
	}
	public void setAge(B age) {
		this.age = age;
	}

	
}

위의 클래스는 부모 클래스로 제네릭 타입 A와 B를 선언해주었다. 각 필드에는 이름과 나이가 들어갈 예정이다. 이제 이러한 부모의 데이터를 물려받을 자식 클래스는 아래와 같다. 

package GenericExtends;

public class Child <A,B,C> extends Parent{
	//제네릭타입을 상속받은 Child 클래스
	private C money;

	public C getMoney() {
		return money;
	}

	public void setMoney(C money) {
		this.money = money;
	}


}

자식 클래스의 경우 <A, B, C> 제네릭 타입을 선언해주고 이후 extends를 통해서 Parent클래스를 상속받았다. 아래는 일반 상속관계와 마찬가지로 새롭게 추가된 제네릭 타입 C(money) 이 필드의 정의와 Getter와 Setter를 만들어 주었다. 이제 메인클래스로 가 해당 클래스들에 데이터를 넣고 실행해보자.


package GenericExtends;

public class main {

	public static void main(String[] args) {
		
		Child<String, Integer, Integer> child = new Child<>();
		//A,B,C의 각 타입을 지정해줌
		
		child.setName("king");
		child.setAge(25);
		child.setMoney(25000);
		
		System.out.println(child.getName() + " / " +child.getAge() + " / " +child.getMoney());
		
	}
}

사용하는 방법은 기존의 클래스와 크게 다르지 않다. 처음 선언시 각 제네릭 타입을 지정해주고 이후 Setter를 통해 각 필드에 데이터를 입력해주고 Getter를 통해 저장된 데이터들을 출력해 주었다. Child 클래스가 Parent클래스를 상속받아 컴파일에 오류 없이 아래와 같은 값을 정상적으로 출력한다.


이제 제네릭타입을 가지는 인터페이스를 알아보자. 아래의 인터페이스는 하나의 캐릭터라는 주제로 공격과 방어라는 추상 메서드 2개를 선언해주었다.

package GenericExtends;

public interface Character<T> {
	public void Attack(T attack);
	public void Defense(T defense);
}

package GenericExtends;

public class RealCharacter<T> implements Character<T> {

	@Override
	public void Attack(T attack) {
		System.out.println(attack + " 만큼의 피해를 입혔다!!!!");
	}
	@Override
	public void Defense(T defense) {
		System.out.println(defense + " 만큼의 피해를 방어했다!!!!");
	}

}

구현 클래스도 단순히 매개 값을 입력받으면 해당 값을 출력하도록 오버 라이딩하였다. 구현 클래스도 마찬가지로 제네릭 타입을 선언해주어야 한다. 그 외에는 일반적인 인터페이스의 구현 클래스와 크게 다르지 않다.

 

이제 해당 구현클래스를 메인클래스에서 실행해보자.


package GenericExtends;

public class main {

	public static void main(String[] args) {
		
		Character<Integer> ch = new RealCharacter<>();
		//인터페이스 객체 생성
		
		ch.Attack(100);
		ch.Defense(100);
		
	}
}

인터페이스 선언시 타입은 Integer 값을 주고 매개 값으로 공격 방어 모두 100의 정수 값을 주었다. 이후 컴파일 진행 시에도 오류 없이 아래와 같이 출력되는 것을 확인할 수 있다.