상세 컨텐츠

본문 제목

Generic 장점과 특징

기록 - 프로그래밍/Java

by wjjun 2020. 6. 28. 16:14

본문

Generic

클래스 내부에서 사용할 데이터 타입을 외부에서 지정합니다.

제네릭을 사용하는 이유 (1) 타입 안정성 (컴파일 시점에 에러 발생)

제네릭은 인스턴스 생성 시점에 타입이 결정 됩니다.

  • outletShop.shopType 타입은 OutletShop
  • editShop.shopType 타입은 EditShop

메인 클래스

public class GenericSampleMain {
  public static void main(String[] args){

    DiscountType<OuletDiscountType> ouletPriceType = new DiscountType<OuletDiscountType>(new OuletDiscountType(false, "1000", "2300"));
    DiscountType<EditDiscountType> editPriceType= new DiscountType<EditDiscountType>(new EditDiscountType(false, "1111"));

    Shop<OutletShop> outletShop = new Shop<OutletShop>(new OutletShop("outlet", 2, ouletPriceType));
    Shop<EditShop> editShop = new Shop<EditShop>(new EditShop("edit", 1, editPriceType));

    if(outletShop.shopType instanceof OutletShop) {
      System.out.println("outletShop");
    } else {
      System.out.println("결과 오류");
    }

    if (editShop.shopType instanceof EditShop) {
      System.out.println("editShop");
    } else {
      System.out.println("결과 오류");
    }

    if(ouletPriceType.discountType.dailyDiscountcode != null){
      System.out.println("아울렛 데일리 할인코드는 " + ouletPriceType.discountType.dailyDiscountcode);
    } else {
      System.out.println("아울렛 데일리 할인코드를 일시적으로 제공하고 있지 않습니다.");
    }

    /* 실행할 때 주석처리 : 컴파일 시점에 에러 발생 dailyDiscountcode */
    if(editPriceType.discountType.dailyDiscountcode != null){
      System.out.println("편집샵은 데일리 할인코드가 없습니다.");
    } else {
      System.out.println("편집샵은 데일리 할인코드가 없습니다.");
    }

    /* 실행할 때 주석처리 : 컴파일 시점에 에러 발생 dailyDiscountcode */
    DiscountType<String> issueDiscountType = new DiscountType<>("기타 할인");
    System.out.println(issueDiscountType.discountType.dailyDiscountcode);
  }
}

---출력---
outletShop
editShop
아울렛 데일리 할인 코드는 2300

제네릭을 사용하면 모든 타입에 대한 사용이 허용되는 것을 방지할 수 있습니다.

사용 가능한 타입을 검증하고 사용할 수 없는 타입은 프로그램이 실행되기 전인 컴파일 시점에 오류가 발생합니다.

  • editPriceType 객체는 dailyDiscountcode 필드가 없는데 호출을 시도하여 컴파일 시점에 오류가 발생합니다.
  • issueDiscountType 객체는 dailyDiscountcode 필드가 없는데 호출을 시도하여 컴파일 시점에 오류가 발생합니다.

프로그램 실행 전 시점에 오류가 발생되어 코드가 수정되어야 하는 사실을 알립니다.

전체 코드

public class Shop<T> {

  public T shopType;

  public Shop(T shopType) {
    this.shopType = shopType;
  }
}

public class OutletShop<T> {

  public String type;
  public int number;
  public T discountType;

  public OutletShop(String type, int number, T discountType) {
    this.type = type;
    this.number = number;
    this.discountType = discountType;
  }
}

public class EditShop<T> {

  public String type;
  public int number;
  public T discountType;

  public EditShop(String type, int number, T discountType) {
    this.type = type;
    this.number = number;
    this.discountType = discountType;
  }
}

public class DiscountType<T> {

  public T discountType;

  public DiscountType(T discountType) {
    this.discountType = discountType;
  }
}

public class OuletDiscountType {

  public boolean isSeasonDiscount;
  public String seasonDiscount;
  public String dailyDiscountcode;

  public OuletDiscountType(boolean isSeasonDiscount, String seasonDiscount,
      String dailyDiscountcode) {
    this.isSeasonDiscount = isSeasonDiscount;
    this.seasonDiscount = seasonDiscount;
    this.dailyDiscountcode = dailyDiscountcode;
  }
}

public class EditDiscountType {

  public boolean isSeasonDiscount;
  public String seasonDiscount;

  public EditDiscountType(boolean isSeasonDiscount, String seasonDiscount) {
    this.isSeasonDiscount = isSeasonDiscount;
    this.seasonDiscount = seasonDiscount;
  }
}

제네릭을 사용하는 이유 (2) 중복 코드 제거

제네릭을 사용하기 전

public class OutletInfo {
    public String type;
}

public class EditInfo {
    public String type;
}

public class OutletShop {
    public OutletInfo info;
    public OutletShop(OutletInfo info){
        this.info = info;
    }  
}

public class EditShop {
    public EditInfo info;
    public EditShop(EditInfo info){
        this.info = info;
    }
}    

OutletShop과 EditShop 클래스 내부가 동일한 것을 확인할 수 있습니다.

제네릭을 사용하면 두 개의 Shop 클래스를 하나로 만들 수 있습니다. (중복 제거)

제네릭을 사용 후

public class OutletInfo {
    public String type;
}

public class EditInfo {
    public String type;
}

public class Shop<T> {
    public T infp;

    public Shop(T info){
        this.info = info;
    }
}

제네릭 특징 (1) extends 키워드 사용

  • extends는 부모의 자식 클래스에 대한 데이터 타입만을 허용합니다.
  • <T(자식) extentds 부모>

extends(상속) 관계에서 사용 가능하며 구현하는 방법은 다음과 같습니다.

abstract class Type{
  public abstract String getType();
}

class OutletType extends Type {

  public String type;
  OutletType(String type) {
    this.type = type;
  }

  public String getType() {
    return this.type;
  }
}

class Shop<T extends Type>{
  public T type;
  Shop(T type){ this.type = type; }
}

public class GenericSampleMain {
  public static void main(String[] args) {
    Shop outlet = new Shop(new OutletType("outlet"));
        /*** 컴파일 시점에 오류
        Shop<String> expectedError = new Shop<String>("outlet");
        */  
    }
}
  1. extends를 사용하여 부모 클래스(Type)의 자식 클래스 데이터 타입만을 허용합니다.

Shop outlet = new Shop(new OutletType("outlet"));

  1. expectedError 객체는 String 타입으로 컴파일 오류가 발생합니다.

Shop expectedError = new Shop("outlet");

implements(구현) 관계에서 사용 가능하며 구현하는 방법은 다음과 같습니다.

public interface Type {
  String getType();
}

public class OutletType implements Type {
  public String type;
  OutletType(String type) { this.type = type;}

  @Override
  public String getType() {
    return this.type;
  }
}

public class Shop<T extends Type> {
  public T type;
  public Shop(T type){
    this.type = type;
  }
}

public class GenericSampleMain {
  public static void main(String[] args) {
    Shop outlet = new Shop(new OutletType("outlet"));
    System.out.println(outlet.type.getType());
    /*** 컴파일 시점에 오류
     Shop<String> expectedError = new Shop<String>("outlet");
     */
  }
}

'기록 - 프로그래밍 > Java' 카테고리의 다른 글

[Stream] Match method  (0) 2020.07.28
[Stream] slice method  (0) 2020.07.27
[Stream] Optional 클래스  (0) 2020.07.23
[Stream] Method references  (0) 2020.07.22
[Stream] map() flatMap()  (0) 2020.07.20

관련글 더보기

댓글 영역