본문 바로가기
Spec UP - Backend/나도코딩의 자바기본편

chap_09. 제네릭 클래스

by TIS_Ha 2023. 6. 21.
반응형

여러 자료형을 받아서 한번에 처리하는 메소드를 제네릭스를 통해 생성해보았다.

https://nossodia.tistory.com/234

 

chap_09. 제네릭스

제네릭스는 다양한 타입의 객체를 지원하는 클래스, 인터페이스, 메소드를 정의하는 방법으로 똑같은 동작을 하는 클래스, 메소드를 여러번 만들 필요없이 한번만 정의하면 여러 타입에서 지원

nossodia.tistory.com

이번 시간에는 예제를 통해 제네릭스 클래스에 대하여 학습해보자.

만약, 특정 카페에서 주문이 완료되면 주문번호 또는 닉네임을 불러 안내해주는 로직을 코드로 작성한다고 생각해보자.

 

우선 주문완료 시 안내하는 코드를 분류해놓을 coffee 패키지를 생성하였다.

1. 주문번호로 안내하는 경우

coffee 패키지 내 CoffeeByNumber 클래스를 만들고 주문번호 waitingNumber 변수와 생성자를 생성하였다.

해당 클래스 내 ready() 메소드가 실행되면 '커피 주문 완료 : 주문번호' 가 출력되도록 메소드를 선언하였다.

2. 닉네임으로 안내하는 경우

coffee 패키지 내 CoffeeByNickname 클래스를 만들고 주문번호 nickname 변수와 생성자를 생성하였다.

해당 클래스 내 ready() 메소드가 실행되면 '커피 주문 완료 : 닉네임'이 출력되도록 메소드를 선언하였다.


chap_09 패키지 내 GenericsClass를 만들고, 위에 생성한 CoffeeByNumber, CoffeeByNickname 객체를 생성하여 c1.ready(), c2.ready() 메소드를 실행하게 되면 각각 "커피주문완료: 주문번호", "커피주문완료: 닉네임"이 정상적으로 출력되게 된다.


그런데 지금 CoffeeByNumber나 CoffeeByNickname이나 실행하는 동작은 동일한 것을 확인해 볼 수 있다.

또한 나중에 주문번호, 닉네임 외에 다른 안내 방식이 추가 된다면 메소드를 추가로 생성해야하는 번거로움이 있다.

이러한 중복된 코드를 삭제하는 방법으로 우선, 오브젝트 클래스를 활용해보자.

오브젝트클래스는 모든 클래스의 조상클래스로 상속을 하지않더라도 자동으로 자식클래스에게 상속되는 특성을 가진다.

오브젝트 클래스의 상속과 다형성을 활용하여 아래와 같이 코드를 생성하였다.

 

coffee 패키지 내 CoffeByName 클래스를 생성하고 Object name 변수와 생성자, 그리고 ready() 메소드를 생성하였다.

그리고 기존의 GenericClass 에서 아래와 같이 객체를 생성하여 c3.ready(), c4.ready()를 실행해보면 정상적으로 실행되는 것을 볼 수 있다.


위의 Object 클래스 예제에서는 사용자 오류가 발생될 수 있는 사항이 있다.

만약 아래와 같이 주문번호와 닉네임의 값을 불러와서 처리해야하는 경우가 있다고 생각해보자.

c3.name과 c4.name은 Object 타입이므로 아래와 같이 int, String 형으로 바로 불러오게 되면 오류가 발생된다.

이 경우에는 아래와 같이 (int) 혹은 (String)을 추가하여 형 변환을 한 후 정상적으로 데이터 사용이 가능하다.

        int c3Name = (int)c3.name;
        System.out.println("주문 고객 번호 : "+ c3Name);
        
        String c4Name = (String)c4.name;
        System.out.println("주문 고객 이름 : "+ c4Name);

만약 이 때 아래와 같이 실수가 발생되었다고 해보자.

c4Name의 데이터타입은 String이고, c3.name의 데이터타입은 int이다.

c3.name을 (String)으로 변환하여 c4Name에 적용하였다.

위 코드상에서는 문제가 발생되지 않은 것처럼 보여지지만 실제 해당 코드를 실행해보면 아래와 같이 오류가 발생되는 것을 볼 수 있다.

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at chap_09._02_GenericClass.main(_02_GenericClass.java:27)

이는 Int형 데이터가 String 데이터로 잘못 지정되었다는 오류이다.

물론 사용자가 실수하지않는 경우에 큰 문제가 발생되지않겠지만, 위 사례의 경우 코드 상에서는 해당 문제가 발견되지 않고 실행 시 문제가 노출되기 때문에 추후 문제가 발생될 여지가 있다.


이러한 문제를 해결하기 위해 제네릭클래스를 활용해보도록 하자.

제네릭스 클래스는 아래와 같이 클래스명 뒤에 <T>를 추가하여 생성할 수 있다.

기존의 GenericClass 에서 위에 생성한 coffee 객체를 생성하여 다시 실행해보자.

GenericClass 객체를 생성할때에는 아래와 같이 < > 꺽쇠(다이아몬드) 기호를 활용하여 선언하는점을 참고하자.

        Coffee<Integer> c5 = new Coffee<>(35);
        Coffee<String> c6 = new Coffee<>("정형돈");

 

제네릭 클래스를 활용하면 Coffee<Integer>, Coffee<String> 과 같이 데이터 자료형을 지정할 수 있다.

Object 클래스를 이용할 경우에는 형 변환을 해야하기 때문에 사용자의 실수가 발생될 가능성이 높지만 제네릭 클래스를 활용하게되면 형변환을 하지 않아도 되기 때문에 사용자 오류를 낮출 수 있다.

 


회원가입기능을 넣어서 커피숍에 가입하는 회원정보를 클래스 객체로 활용하게 되었다고 생각해보자.

그렇다면 단순한 문자열이 아닌 이름, 전화번호, 포인트 적립 등 사용자정보를 클래스로 관리하는 패키지를 만들어보자.

 

user 패키지를 생성하여 User 클래스를 생성하였다.

User 클래스 내에서는 고객의 성명을 관리하고 addPoint() 메소드 실행 시 "~님, 포인트 적립되었습니다." 안내가 출력된다.

위의 User 클래스를 상속받는 VIPUser 클래스를 생성하였다.

VIPUser 클래스 내에서는 고객 성명 앞에 "특별한 ~ 님" 을 추가하도록 하였다.

기존 coffee 패키지 내 CoffeeByUser 클래스를 추가로 생성하였다.

여기서 CoffeByUser <T Extends User>은 어떤 형태의 타입이건 상관 없으나 User라는 클래스를 상속하는 <T>를 사용해야한다는 의미이다. (User, VIPUser)

이처럼 제네릭 클래스를 생성할 때 원하는 데이터 유형의 제한을 걸 수 있다.

 

위와 같이 c7, c8의 객체를 생성 후 ready() 메소드를 실행하면 각각 아래와 같이 출력한다.

"커피 주문 완료 : 강호동" "강호동님, 포인트 적립되었습니다."

"커피 주문 완료 : 서장훈" "특별한 서장훈님, 포인트 적립되었습니다.

 

만약 위에서  User클래스를 상속하지 않는 클래스를 생성하게 되면 오류가 발생된다.


이번에는 제네릭클래스에서 <T> 값 하나가 아닌 여러개 값 유형을 받는 경우를 실습해보자.

먼저 모든 <T> 유형을 받아 "커피주문완료 : name" 을 출력하는 orderCoffee 메소드를 생성해보았다.

orderCoffee(35) 를 실행하면 커피주문완료 : 35가 출력될 것이다.

이때 주문한 커피 종류까지 함께 출력할 수 있는 메소드를 생성해보자.

orderCoffee(36,"카페라떼") 를 메소드를 실행하면 "카페라떼 준비완료 : 36" 이 출력된다.

위와 같이 T, V 두개 이상의 데이터를 한꺼번에 처리할 수도 있다.

 

반응형

'Spec UP - Backend > 나도코딩의 자바기본편' 카테고리의 다른 글

chap_09. ArrayList  (0) 2023.06.28
chap_09. Wrapper 클래스  (0) 2023.06.28
chap_09. 제네릭스  (0) 2023.06.21
Chap_08.인터페이스(Interface)  (0) 2023.05.10
Chap_08. 추상 클래스(AbstractClass)  (0) 2023.05.10

댓글