Class11(열거형, 인터페이스, 제네릭)
2023. 01. 17. 수업내용 정리
열거형, 인터페이스, 제네릭
열거형
- 열거형(Enumeration Type)은 어떠한 것의 종류가 의미론적으로 참과 거짓이 아닌 두 개 이하로 나누어 지거나, 세 가지 이상으로 나누어질 때 사용한다.
- 열거형의 명명법은 파스칼 케이스를 따르고, 클래스와 마찬가지로 그 자체가 타입이 된다.
- 수동으로 객체화할 수 없고 열거형이 가지는 열거된 인자들이 그 값이 되는데, 이 때 이 값들은 정적이고 읽기 전용인 열거형 타입의 객체이다.
public enum [열거형 이름]{ [인자,...]? }
- 열거형의 인자들은 콤마(,)로 구분하여 여러개 적을 수 있다.
- 단, 인자들 간에 같은 이름을 가지는 것이 있어서는 안 된다.
- 앞서 얘기 했듯이 인자들은 정적이며 읽기 전용이다.
- 모든 열거형 인자는 정적임으로 프로그램 실행 중에 단 하나밖에 존재할 수가 없음으로 동등 비교(
==
)및 부등 비교(!=
)를 한다. (사실equals
써도 관계 없음)
열거형의 고급적 사용
- 열거형 인자의 나열이 끝나고 세미콜론(
;
)을 적어, 열거형 타입에 대한 멤버를 직접 구성할 수 있다.(클래스 처럼) - 각 인자 뒤에 괄호(
(,)
)를 이용하여 생성자에 전달할 전달 인자를 전달해 줄 수 있다. 생성자가 매개 변수를 가지지 않는다면 주로 생략한다.
인터페이스
- 상속(Inheritance) 관계가 클래스 간의 기능 확장에 중점을 뒀다면, 인터페이스(Interface) 구현(Implementation)은 어떠한 클래스로 하여금 이에 속성이나 특성 등을 부여하거나 기능상의 골조를 만들기 위해 사용한다.
- 명명법은 기본적으로 파스칼 케이스를 따르다, 대문자
I
로 시작하게 하기도 한다.I(명사)
,I(동명사)
,I(-able)
혹은I
없이(명사)
,(동명사)
,-able
- 인터페이스가 가지는 모든 멤버 변수는
public
이고 정적이고 읽기 전용일 수 밖에 없다. - 인터페이스가 가지는 모든 메서드는
public
이고 (일반적으로)추상적이다. - 인터페이스가 가지는 메서드가 구현부를 가지게 하기 위해 아래와 같이
default
키워드를 이용할 수 있다.public interface [인터페이스 이름] { default [반환 타입 | void] [메서드 이름]{ // 구현부 } }
이 때,
default
는 메서드를 추상화하지 않겠다는 키워드이며 접근 제한자가 아님에 유의한다.
제네릭(Generic)
- 제네릭(Generic)은 어떠한 타입 A가 다른 타입 B에 대한 멤버(변수, 메서드의 반환 타입, 매개 변수 타입 등)를 가지고 이 타입 B가 동적으로 변하여 A 타입을 다분화하지 않고 능동적으로 사용하기 위해 존재한다.
- 단, 제네릭 타입은 기초 타입일 수 없음에 유의한다.
public class MonsterBall<T extends Mob> { private T monster; public T getMonster(){ return this.monster; } public void setMonster(T monster) { this.monster = monster; } }
- 위 클래스
MonsterBall
은T
를 제네릭으로 가지는 클래스이고, 이 때T
는Mob
클래스(혹은 인터페이스)를 상속 받음을 강제한다. - 위 클래스에서
T
는 가상의 타입이고 명명법은T[파스칼 케이스]
로 하는 편이다. (가령,TKey
,TValue
등) - 특정 제네릭에 대한 클래스는 타입으로 사용할 수 있음으로 아래 처럼 변수의 타입으로 사용될 수 있다.
MonsterBall<Wyvern> wmb = new MonsterBall<Wyvern>();
- 위 객체화 연산에서 객체를 넘겨 받는 타입의 제네릭과 객체화 할 때의 제네릭이 같다면 객체화시의 제네릭 타입은 아래와 같이 생략 가능하다.
MonsterBall<Wyvern> wmb = new MonsterBall<>();
다이나믹 제네릭(Dynamic Generic)
- 위 클래스
- 제네릭의 선언부가 아닌 곳에서(클래스 이름 뒤 말고)
?
특수 문자를 활용하여 그 타입이 정확히 정해지지 않은 타입에 대한 제네릭을 활용할 수 있다.MonsterBall<Wyvern> wmb = new MonsterBall<>(); MonsterBall<? extends Mob> someMb = wmb;
위 코드에서 변수
someMb
는 그 타입이 정확히 지정되지 않았지만Mob
클래스를 상속 받는(? extends Mob
)제네릭 타입에 대한MonsterBall
타입임으로MonsterBall<Wyvern>
타입인 변수wmb
를 받을 수 있다.
멀티 타입 파라미터 제네릭(Multi-type Parameter Generic)
- 멀티 타입 파라미터 제네릭은 어떠한 타입이 제네릭을 두 개 이상 가지는 것을 의미하며, 주로
HashMap
혹은 튜플 구현에 사용한다. - 튜플은 서로 다른 두 타입의 값을 쌍(pair)으로 가지기 위한 타입이다.
- 3개 타입에 대한 값을 가지는 타입을 3-튜플(
3-Tuple
혹은Triple
혹은Triplet
이라 한다.) 그 이상은 잘 안 쓰는데 궁금하면 검색.
- 3개 타입에 대한 값을 가지는 타입을 3-튜플(
부가적인 이야기
- 부모 타입의 변수가 자식 객체를 받을 수 있는 것을 다형성의 일환으로 보는 것처럼 원형이 부모 타입인 아형이 원형이 자식 타입인 아형의 부모처럼 작동하는 것을 공변성(Covariant)이라고 한다. 가령,
Object[]
은String[]
의 부모 타입으로 인식되고 이를공변성을 가진다
라고 한다. 하지만, 제네릭은 공변성(Covariant)을 가지지 않음으로List<Object>
를List<String>
의 부모라고 하지 않는다. - 단, 자바 컴파일러의 트릭으로, 제네릭이 공변성을 가지는 것처럼 작동할 수 있게 하는데, 이가 다이나믹 제네릭의 상속이다. 가령,
List<? extends Object>
가List<String>
의 부모인냥 작동할 수 있게 하는 것이다. - 반대로,
List<? super String>
의 꼴에서 이가 가지는 인자는 [String
이 상속 받고 있는 아무 타입]으로, 위extends
와 반대의 의미이고 이를 반공변성(Contravariant)라고 한다.
댓글남기기