매개변수화된 추상 자료형
int 스택과 문자열 스택을 따로 만들어야 할까?
문제
달라지는 곳은 타입 하나
정적 타입 언어는 변수의 타입을 실행 전에, 곧 컴파일할 때 정하는 언어입니다(4강). 그래서 스택에 담을 요소의 타입도 미리 적어야 합니다. 정수 스택, 실수 스택, 문자열 스택을 따로 만들면 타입 한 군데만 다른 클래스가 셋 생깁니다.
컴파일은 소스를 기계어로 번역하는 일이고, 요소는 스택에 든 값 하나입니다. 세 줄의 코드는 예시입니다.
매개변수화된 추상 자료형
타입 자리를 빈칸으로
요소 타입을 빈칸으로 두고 클래스를 한 번만 정의합니다. 쓸 때 빈칸에 타입을 넣으면 그 타입의 스택이 됩니다. 이것이 매개변수화된 추상 자료형(parameterized ADT)이고, 제네릭 클래스(generic class)라고도 합니다.
매개변수는 함수가 값을 넘겨받는 변수입니다. 여기서는 값 대신 타입을 넘겨받습니다. C++, 자바 5.0, C# 2005가 지원합니다.
C++ 첫째: 생성자의 매개변수
크기는 넘겨받습니다
C++의 클래스는 생성자가 매개변수를 받게 해서 어느 정도는 제네릭하게 만들 수 있습니다. 크기를 넘겨받으면 클래스 하나로 크기가 다른 스택을 만듭니다. 다만 요소 타입은 그대로 int입니다.
이 강의가 따르는 교재의 예입니다. 150을 넘기면 마지막 칸의 번호 maxLen은 150 - 1 = 149가 됩니다.
C++ 둘째: 템플릿 클래스
Type이 타입의 빈칸
요소 타입까지 비워 두려면 클래스를 템플릿 클래스(template class)로 만듭니다. template 줄에서 타입 매개변수 Type을 선언하고, 클래스 안의 요소 타입 자리에 씁니다. 빈칸에 실제 타입을 넣어 쓰는 것을 인스턴스화(instantiation)라고 합니다.
Stack<int>처럼 꺾쇠 안에 넣을 타입을 적습니다.
자바 5.0의 제네릭
T 하나로 클래스 전체를
자바는 클래스 이름 뒤 꺾쇠에 타입 매개변수 T를 적습니다. 요소를 담는 ArrayList의 타입도, push가 받는 값의 타입도 T입니다. 인스턴스화할 때 String을 적으면 문자열만 담는 스택이 됩니다.
교재의 Stack2 예입니다. ArrayList는 자바에 미리 준비된 컬렉션(여러 값을 담는 클래스)입니다. {…}는 본문을 줄였다는 표시입니다.
자바 제네릭의 규칙
타입 자리에는 클래스만
자바에서 제네릭 매개변수는 클래스여야 합니다. int 같은 기본형은 넣을 수 없어 Integer 같은 클래스를 씁니다. 요소 타입이 미리 정해지니 다른 타입이 섞이지 않고, 꺼낼 때 캐스팅도 필요 없습니다.
기본형은 int처럼 언어에 원래 있는 타입이고, Integer는 int를 감싼 클래스입니다. 캐스팅은 프로그래머가 타입을 직접 바꾸는 것입니다. "abc"는 예시입니다.
C# 2005의 제네릭
자바와 둘이 다릅니다
C# 2005의 제네릭은 자바 5.0과 비슷합니다. 다른 점은 둘입니다. 와일드카드 클래스가 없고, 제네릭 구조의 요소에 배열처럼 첨자(몇 번째인지 나타내는 번호)로 닿을 수 있습니다.
와일드카드는 타입 자리에 ?를 적어 어떤 타입이든 받게 하는 것입니다. 자바의 제네릭 컬렉션은 add, get 같은 메서드로 요소를 다룹니다.
다음 편