SqueakByExample:8.2
Number
놀랍게도, 스몰토크에서의 숫자들은 원시데이터가 아닌 진짜 객체 입니다. 물론 숫자들은 가상 머신에서 효과적으로 동작합니다만, Number 의 계층은 스몰토크 클래스 계층의 다른 부분들처럼 완전하게 접근 및 확장이 가능합니다.
Number(숫자형)과 관련된 내용은 kernel-number 카테고리에서 찾을 수 있습니다. 이 계층의 상위는 Magnitude 이며, Magnitude 는 비교 연산자를 지원하는 모든 종류의 클래스들을 의미합니다. Number 는 다양한 산술 요소를 추가할 수 있습니다. 이런 연산자의 대부분이 추상메서드 입니다. Float 와 Fraction 은 각각 부동소수점(실수)과 분수를 나타냅니다. Integer 또한 추상클래스 이며, 추상클래스인 Integer 는 하위 클래스인 SmallInteger, LagePositiveInteger, LargeNegativeInteger 등과는 다르게 구별됩니다. 일반적인 경우, 값이 요구하는 만큼 자동으로 변환되므로, 유저들은 3 개의 정수 클래스들 사이의 차이점들에 대해 신경을 써야 할 필요는 없습니다.
Magnitude
Magnitude 는 Number 클래스의 부모클래스일 뿐만 아니라 Character, Duration, Timespan 처럼 연산을 지원하는 클래스들의 부모이기도 합니다.(Complex(복소수)는 비교가 불가능합니다. 그래서 Number 를 상속받지는 않습니다)
< 과 = 메서드는 추상메서드입니다. 그외 다른 연산자들은 일반적인 방법으로 정의됩니다. 예를 들자면 다음과 같습니다:
메서드 8.12: 추상 비교 메서드
Magnitude>> < aMagnitude
"Answer whether the receiver is less than the argument."
↑self subclassResponsibility
Magnitude>> > aMagnitude
"Answer whether the receiver is greater than the argument."
↑aMagnitude < self
Number
Magnitude 비슷하게 Number 에서 +, -, *, / 등은 추상메서드로 정의합니다만, 그외의 다른 산술 연산자들은 일반형적 형태로 정의됩니다.
모든 Number 객체들은 asFloat 과 asInteger 같은 다양한 변환 연산자를 지원합니다. 이런 연산자중에는, Number 를 실수부가 0 인 복소수의 인스턴스로 변환하는 i 나, Number 에서 Duration 객체를 생성하는 hour, day, week 등이 있습니다.
Number 는 sin, log, raiseTo:, squared, sqrt 등과 같은 일반 수학 기능을 직접 지원합니다.
Number>>printOn: 은 Number>>printOn:base: 의 추상메서드로 구현되어 있습니다(Number>>printOn: 의 경우 base에 해당되는 기본값은 10으로 지정되어 있습니다.)
Testing 메서드의 종류에는, even, odd, positive, negative 등이 있습니다. 당연히, Number 는 isNumber를 재지정(override)하고 있습니다. 재미있는 점은 isInfinite 는 false 를 반환하도록 정의되어 있다는 것입니다.
Truncation 메서드에는 floor, ceiling, intergerPart, fractionPart 등이 있습니다.
1 + 2.5 | ⇒ 3.5 | "Addition of two numbers" |
3.4 * 5 | ⇒ 17.0 | "Multiplication of two numbers" |
8/2 | ⇒ 4 | "Division of two numbers" |
10 -- 8.3 | ⇒ 1.7 | "Subtraction of two numbers" |
12 = 11 | ⇒ false | "Equality between two numbers" |
12 ∼= 11 | ⇒ true | "Test if two numbers are different" |
12 > 9 | ⇒ true | "Greater than" |
12 >= 10 | ⇒ true | "Greater or equal than" |
12 < 10 | ⇒ false | "Smaller than" |
100@10 | ⇒ 100@10 | "Point creation" |
다음 예제는 스몰토크에서 문제없이 잘 작동합니다:
1000 factorial / 999 factorial ⇒ 1000
1000 factorial 을 다른언어로 계산하는건 쉽지 않습니다만 별다른 어려움없이 계산이 된다는점을 주의해 주시기 바랍니다. 위의 예제는 숫자에 대한 자동 형변환과 정확한 숫자의 정확한 제어에 대한 좋은 예입니다.
1000 factorial 의 결과 출력을 시도해 보시기 바랍니다. 이 작업은 계산하는 것보다 출력에 더 많은 시간이 걸립니다.
Float
Float 는 부동소수점을 위한 Number 의 추상메서드로 구현되어 있습니다.
여기서 흥미로운점은 Float 클래스(예컨데 Float의 class-side)는 다음 정수를 반환합니다: e, infinity, nan, pi 등
Float pi | ⇒ 3.141592653589793 |
Float infinity | ⇒ Infinity |
Float infinity isInfinite | ⇒ true |
Fraction
Fraction(분수) 은 분자와 분모에 쓰이는 인스턴스 변수들로 표시되며, 각 분자와 분모는 반드시 정수여야 합니다. 분수는 일반적으로 정수의 나눗셈으로 만들어 집니다. (Fraction>>numerator:denominator: 를 사용하는것 보다는 constructor 메서드가 낫습니다.)
6/8 | ⇒ (3/4) |
(6/8) class | ⇒ Fraction |
정수 또는 다른 분수로 분수를 곱하기 하면, 답이 정수가 될 수 있습니다.
6/8 * 4 | ⇒ 3 |
Integer
Integer(정수) 는 3 개의 구체적 정수 구현에 대한 추상적 부모 클래스입니다. Integer 는 많은 추상 Number 메서드의 구체적인 구현을 제공할 뿐만 아니라, factorial, atRandom, isPrime, gcd 등의 정수 특유의 메서드 및 그외 많은 메서드를 추가합니다.
SmallInteger는 인스턴스가 간결하게 표시된다는 면에서 특별합니다-SmallInteger는 값을 참조로서 저장하는 대신, 참조를 유지하기 위해 비트 영역을 사용해 직접 표현합니다. 객체참조의 첫 번째 비트는 객체가 SmallInteger 인지 아닌지를 가리킵니다.
클래스 메서드 minVal 과 maxVal 은 SmallInteger 의 범위를 알려줍니다.
SmallInteger maxVal = ((2 raisedTo: 30) -- 1) | ⇒ true |
SmallInteger minVal = (2 raisedTo: 30) negated | ⇒ true |
SmallInteger 가 이 범위를 벗어나면, LargePositiveInteger 로 자동으로 변환되거나 또한 필요한 만큼 LargeNegetiveInteger 로 자동으로 변환됩니다:
(SmallInteger maxVal + 1) class | ⇒ LargePositiveInteger |
(SmallInteger minVal -- 1) class | ⇒ LargeNegativeInteger |
마찬가지로, 큰 정수들은 알맞은 시기에 작은 정수들로 다시 변환됩니다.
대부분의 프로그래밍 언어에서 처럼, 정수들은 지정동작의 반복에 유용합니다. 블록을 반복적으로 평가하는 작업에 사용되는 전용 메서드 timesRepeat 이 있습니다. 3장에서 비슷한 예제를 이미 본적이 있죠.
n := 2.
3 timesRepeat: [ n := n*n ].
n ⇒ 256