220614_인터넷 강의_제네릭 프로그래밍

창고·2022년 10월 20일
0

티스토리에 저장했던 글을 옮겼습니다.
https://mrcocoball.tistory.com/86

1. 제네릭(Generic) 프로그래밍

(1) 제네릭 자료형 정의

  • 클래스에서 사용하는 변수의 자료형이 여러 개 인데 그 기능(메소드)는 동일할 경우
    클래스의 자료형을 특정하지 않고 추후 해당 클래스를 사용할 때 지정할 수 있도록 선언
  • 실제 사용되는 자료형의 변환은 컴파일러에 의해 검증되므로 안정적인 프로그래밍 방식
  • 컬렉션 프레임워크에서 많이 사용됨
  • 제네릭 클래스의 정의 예시
    • 자료형 매개변수 T(type parameter) : 이 클래스를 사용하는 시점에 실제 사용할 자료형을 지정, static 변수는 사용 불가
    • GenericIdol : 제네릭 자료형
    • E : element, K : key, V : value 등 여러 알파벳을 의미에 따라 사용 가능
public class GenericIdol<T> { // T extends 사용
	
	   // field
	   
	   private T idolGroup; // T 타입의 변수 idolGroup


	   public T getIdolGroup() { // T 타입을 반환하는 제너릭 메소드
	      return idolGroup;
	   }

	   public void setIdolGroup(T idolGroup) {
	      this.idolGroup = idolGroup;
	   }

	   public String toString() {
	      return idolGroup.toString();
	   }
}
  • [Aqours.java]
public class Aqours extends {
	
	   public String toString() {
		      return "Aqours 소속의 타입입니다.";
	  }
}      
  • [Liella.java]
public class Liella extends IdolGroup {
	
	   public String toString() {
		      return "Liella 소속의 타입입니다.";
	  }
}      
  • [GenericIdolTest.java]
public class GenericIdolTest {

	public static void main(String[] args) {
		
		GenericIdol<Aqours> aqoursIdol = new GenericIdol<Aqours>(); // Aqours 자료형의 aqoursIdol으로 지정 
		aqoursIdol.setIdolGroup(new Aqours());
		Aqours aqours = aqoursIdol.getIdolGroup(); // 형변환 하지 않음**
		System.out.println(aqoursIdol);

		GenericIdol<Liella> liellaIdol = new GenericIdol<Liella>(); // Liella 자료형의 liellaIdol으로 지정
		liellaIdol.setIdolGroup(new Liella());
		Liella liella = liellaIdol.getIdolGroup(); // 형변환 하지 않음**
		System.out.println(liellaIdol);

	}

}

(2) 다이아몬드 연산자 <>

  • ArrayList list = new ArrayList<>(); // 다이아몬드 연산자 내부에서 자료형 생략 가능
  • 제네릭에서 자료형 추론
ArrayList list = new ArrayList() => var list = new ArrayList();

2. <T extends 클래스> 사용

(1) T extends를 사용한 프로그래밍

  • 상위 클래스를 통해 T 자료형의 범위를 제한
  • 상위 클래스에서 선언하거나 정의하는 메소드를 활용할 수 있음
  • 상속을 받지 않는 경우 T는 Object로 변환되어 Object 클래스가 기본으로 제공하는 메소드만 사용 가능

(2) 예제

  • GenericIdol에 idolGroup 변수의 자료형을 상속 받아 구현
  • T에 무작위 클래스가 들어갈 수 없게 IdolGroup 클래스를 상속 받은 클래스로 한정
  • [IdolGroup.java]
public abstract class IdolGroup {
	
	   public abstract void posing();

}
  • [Aqours.java]
public class Aqours extends IdolGroup {
	
	public String toString() {
		return "Aqours 소속의 타입입니다.";
	}
	   
	public void posing() {
		System.out.println("Aqours의 포즈를 취합니다.");
	}

}
  • [Liella.java]
public class Liella extends IdolGroup {
	
	public String toString() {
		return "Liella 소속의 타입입니다.";
	}
	   
	public void posing() {
		System.out.println("Liella의 포즈를 취합니다.");
	}
}
  • [GenericIdol.java]
  • [GenericIdolTest.java]
public class GenericIdolTest {

	public static void main(String[] args) {
		
		GenericIdol<Aqours> aqoursIdol = new GenericIdol<Aqours>(); // Aqours 자료형의 aqoursIdol으로 지정 
		aqoursIdol.setIdolGroup(new Aqours());
		Aqours aqours = aqoursIdol.getIdolGroup(); // 형변환 하지 않음**
		System.out.println(aqoursIdol);
		aqours.posing();

		GenericIdol<Liella> liellaIdol = new GenericIdol<Liella>(); // Liella 자료형의 liellaIdol으로 지정
		liellaIdol.setIdolGroup(new Liella());
		Liella liella = liellaIdol.getIdolGroup(); // 형변환 하지 않음**
		System.out.println(liellaIdol);
		liella.posing();

	}

}

3. 제네릭 메소드 활용

(1) 제네릭 메소드의 정의

  • 자료형 매개변수를 메소드의 매개변수나 반환 값으로 가지는 메소드
  • 자료형 매개 변수가 하나 이상인 경우도 있음
  • 제네릭 클래스가 아니어도 내부에 제네릭 메소드 구현하여 사용 가능
  • 형태
public <자료형 매개 변수> 반환형 메소드 이름(자료형 매개변수...) {}

(2) 활용 예제

  • 두 점(top, bottom)을 기준으로 사각형 만들 때 사각형의 넓이를 구하는 메소드
  • 두 점은 정수인 경우도, 실수인 경우도 있으므로 제네릭 타입 사용
public class Point<T, V> {
	
	// field
	
	T x;
	V y;
	
	Point(T x, V y) {
		this.x = x;
		this.y = y;
	}
	
	public T getX() {
		return x;
	}
	
	public V getY() {
		return y;
	}

}
public class GenericMethod {
	
	public static <T,V> double makeRectangle(Point<T,V> p1, Point<T,V> p2) {
		// Point 점인 p1, p2인데 타입이 T,V인 것에 대해 makeRectangle
		
		double left = ((Number)p1.getX()).doubleValue();
		double right = ((Number)p2.getX()).doubleValue();
		double top = ((Number)p1.getY()).doubleValue();
		double bottom = ((Number)p2.getY()).doubleValue();
		
		double width = right - left;
		double height = bottom - top;
		
		return width * height;
		
	}

	public static void main(String[] args) {
		Point<Integer, Double> p1 = new Point<Integer, Double>(0, 0.0);
		Point<Integer, Double> p2 = new Point<Integer, Double>(10, 10.0);
		
		double size = GenericMethod.<Integer, Double>makeRectangle(p1, p2); // static 메소드이므로 GenericMethod.로 접근
		System.out.println(size);

	}

}
profile
공부했던 내용들을 모아둔 창고입니다.

0개의 댓글