ComputerProgrammingwithGNUSmalltalk:5.7
클래스 확장과 변경
프로그램에서 수의 세제곱을 많이 계산한다고 가정해봅시다. Number 클래스가 수신자 객체의 세제곱수를 답하는 cubed라는 메소드를 가지고 있는 것이 아주 유용하지 않겠습니까? 프로그래머는 자주 그런 식으로 클래스를 수정할 필요가 있으며, GNU 스몰토크는 그러한 방법을 제공합니다. 내장된 클래스도 프로그래머가 만든 클래스도 수정할 수 있습니다.
따라서 여러분은 클래스 내의 새로운 메소드를 추가하거나 기존 메소드를 수정할 수 있습니다. 클래스를 수정하기 위한 일반 문법은 다음과 같습니다.
className extend [
| newInstanceVariable1 newInstanceVariable2 |
methodSelector [
...
]
]
인스턴수 변수들을 클래스에 추가할 수 있습니다.
만약 같은 선택자의 메소드가 이미 정의되었다면, 마지막 메소드가 나머지 모두를 대체하며 새롭게 구현할 것입니다.
만약 같은 선택자의 메소드가 존재하지 않는다면, 추가할 것입니다.
클래스 자체를 고치길 원한다면, 여러분은 예시처럼 className 다음에 class를 추가합니다.
className class extend [
| newClassVariable1 newClassVariable2 |
methodSelector [
...
]
]
이번에는 클래스변수와 클래스메소드를 만든 것이라는 점에 유의하세요.
이제 Human 클래스를 만들고 수정하여봅시다. Human 클래스의 핵심 버전은 같은 공통 속성을 갖을 것이며, 기본 메시지에 답변할 수 있을 것입니다.
"human.st"
"Human 클래스의 핵심버전"
Object subclass: Human [
| name age |
setName: aName [
name := aName.
]
getName [
^name
]
setAge: anAge [
age := anAge.
]
getAge [
^age
]
introduceYourself [
Transcript show: 'Hello, my name is ', name, ' and I''m ', age printString, ' years old.'; cr.
]
> aHuman [
^age > aHuman getAge
]
< aHuman [
^age < aHuman getAge
]
= aHuman [
^age = aHuman getAge
]
]
| me myBrother |
me := Human new.
me setName: 'Canol Gökel'.
me setAge: 24.
myBrother := Human new.
myBrother setName: 'Gürol Gökel'.
myBrother setAge: 27.
me introduceYourself.
myBrother introduceYourself.
(me < myBrother) printNl.
Hello, my name is Canol Gökel and I'm 24 years old.
Hello, my name is Gürol Gökel and I'm 27 years old.
true
우리 Human 클래스는 아주 간단합니다. name과 age로 이름 붙인 두 개의 인스턴스 변수가 있습니다. 접근자(setName:, getName 등)를 정의한 다음에 introduceYourself라고 이름 붙인 메소드를 정의하였습니다. Human 객체가 이 메시지를 받으면 객체가 가지고 있는 어떤 정보를 스스로 말하여 자기 자신을 소개합니다. 두 Human의 나이를 비교하는 메소드 또한 작성하였습니다. 만약 두 Human 객체간의 비교하길 원한다면, 여러분은 이항 메시지인 >, < 나 =을 사용할 수 있습니다. 수신자 객체의 나이를 접근할 때는 age라는 인스턴스 변수를 사용하였고, 인자 객체의 나이를 접근할 때는 getAge라는 메시지를 보냈다는 차이점을 주의깊게 보아 주십시오. 비교 메소드는 이미 Integer 객체에서 정의하였으며, 더 이상 깊게 들어가지 않겠습니다.
이 구현은 아주 간단합니다. 이 클래스에 좀더 세부적인 것을 추가하고 싶다고 칩시다. 위의 코드를 직접 고쳐도 되겠지만, 그렇게 할 수 없을 때도 있을 겁니다. 예를 들어, 하나 이상의 프로그램이 코드를 공유하고 있고, 그 중 하나의 객체만 확장된 버전이 필요할 때가 있습니다. 그런 경우에는 원본 코드를 유지하는 것이 좋은 생각입니다. 자, 그럼 새로운 시험용 프로그램에서 Human 클래스를 확장해 봅시다. 표시된 부분에는 이전의 Human 클래스의 코드를 복사해서 붙여넣으십시오.
"human_extended.st"
"Human클래스를 확장한 프로그램"
... -> 여기에 옛 Human클래스의 코드를 붙여 넣으세요.
Human extend [
| occupation experience |
getOccupation [
^occupation
]
setOccupation: anOccupation [
occupation := anOccupation.
]
getExperience [
^experience
]
setExperience: anExperience [
experience := anExperience.
]
introduceYourself [
Transcript show: 'Hello, my name is ', name, ' and I''m ', age printString, ' years old. I am ', occupation, '.'; cr.
]
> aHuman [
^experience > aHuman getExperience
]
< aHuman [
^experience < aHuman getExperience
]
= aHuman [
^experience = aHuman getExperience
]
]
| me myFriend |
me := Human new.
me setName: 'Canol Gökel'.
me setAge: 24.
me setOccupation: 'an Engineer'.
me setExperience: 1.
myFriend := Human new.
myFriend setName: 'İsmail Arslan'.
myFriend setAge: 23.
myFriend setOccupation: 'an Engineer'.
myFriend setExperience: 3.
me introduceYourself.
myFriend introduceYourself.
(me > myFriend) printNl.
Hello, my name is Canol Gökel and I'm 24 years old. I am an Engineer.
Hello, my name is İsmail Arslan and I'm 23 years old. I am an Engineer.
false
우리는 위 코드에서 많은 작업을 했습니다. 하나씩 살펴 봅시다. 맨 처음에 한 일은 occupation과 experience라는 두 개의 인스턴스 변수를 추가한 것입니다. occupation은 직업을 뜻하며, experience는 경력을 뜻합니다.
| occupation experience |
그런 다음, 우리는 새 인스턴스 변수들을 위한 접근자 메소드들을 작성하였습니다.
getOccupation [
^occupation
]
setOccupation: anOccupation [
occupation := anOccupation.
]
getExperience [
^experience
]
setExperience: anExperience [
experience := anExperience.
]
이들 메소드들은 전에 작성된 적이 없기 때문에, 기존 클래스에 추가 되었습니다. 그런 다음, 우리는 몇몇 메소드를 재작성하였습니다.
introduceYourself [
Transcript show: 'Hello, my name is ', name, ' and I''m ', age printString, ' years old. I am ', occupation, '.'; cr.
]
> aHuman [
^experience > aHuman getExperience
]
< aHuman [
^experience < aHuman getExperience
]
= aHuman [
^experience = aHuman getExperience
]
이 메소드들은 오래된 구현을 오버라이딩(overridding) 했습니다. 새 소개 메소드는 Human의 직업도 포함하고 있습니다. 비교 메소드도 변경하여서 이번에는 Human 객체의 경력에 따라 비교가 이뤄질 것입니다. 이런 변경은 마치 인사과에서 그들의 프로그램에서 Human클래스를 쓰기 위해 번경한 것 같군요.