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

2020-12-20


etc-image-0

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


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

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클래스를 상속받아 컴파일에 오류 없이 아래와 같은 값을 정상적으로 출력한다.

etc-image-1


이제 제네릭타입을 가지는 인터페이스를 알아보자. 아래의 인터페이스는 하나의 캐릭터라는 주제로 공격과 방어라는 추상 메서드 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의 정수 값을 주었다. 이후 컴파일 진행 시에도 오류 없이 아래와 같이 출력되는 것을 확인할 수 있다.

etc-image-2