www.delorie.com/gnu/docs/smalltalk/gst_84.html | search |
Buy GNU books! | |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
If we were programming an application which did a large amount of complex math, we could probably manage it with a number of two-element arrays. But we'd forever be writing in-line code for the math and comparisons; it would be much easier to just implement an object class to support the complex numeric type. Where in the class hierarchy would it be placed?
You've probably already guessed--but let's step down the
hierarchy anyway. Everything inherits from Object, so
that's a safe starting point. Complex numbers can not be
compared with <
and >
, and yet we strongly suspect that,
since they are numbers, we should place them under the Number
class. But Number inherits from Magnitude--how do we
resolve this conflict? A subclass can place itself under a
superclass which allows some operations the subclass doesn't
wish to allow. All that you must do is make sure you intercept
these messages and return an error. So we will place
our new Complex class under Number, and make sure to disallow
comparisons.
One can reasonably ask whether the real and imaginary parts of our complex number will be integer or floating point. In the grand Smalltalk tradition, we'll just leave them as objects, and hope that they respond to numeric messages reasonably. If they don't, the user will doubtless receive errors and be able to track back their mistake with little fuss.
We'll define the four basic math operators, as well as
the (illegal) relationals. We'll add printOn:
so that the
printing methods work, and that should give us our Complex
class. The class as presented suffers some limitations,
which we'll cover later in the chapter.
Number subclass: #Complex instanceVariableNames: 'realpart imagpart' classVariableNames: '' poolDictionaries: '' category: nil ! !Complex class methodsFor: 'creating'! new ^self error: 'use real:imaginary:' ! new: ignore ^self new ! real: r imaginary: i ^(super new) setReal: r setImag: i ! ! !Complex methodsFor: 'creating--private'! setReal: r setImag: i realpart := r. imagpart := i. ^self ! ! !Complex methodsFor: 'basic'! real ^realpart ! imaginary ^imagpart ! ! !Complex methodsFor: 'math'! + val ^Complex real: (realpart + val real) imaginary: (imagpart + val imaginary) ! - val ^Complex real: (realpart - val real) imaginary: (imagpart - val imaginary) ! * val ^Complex real: (realpart * val real) - (imagpart * val imaginary) imaginary: (imagpart * val real) + (realpart * val imaginary) ! / val | d r i | d := (val real * val real) + (val imaginary * val imaginary). r := ((realpart * val real) + (imagpart * val imaginary)). i := ((imagpart * val real) - (realpart * val imaginary)). ^Complex real: r / d imaginary: i / d ! ! !Complex methodsFor: 'comparison'! = val ^(realpart = val real) & (imagpart = val imaginary) ! > val ^self shouldNotImplement ! >= val ^self shouldNotImplement ! < val ^self shouldNotImplement ! <= val ^self shouldNotImplement ! ! !Complex methodsFor: 'printing'! printOn: aStream aStream nextPut: $(. realpart printOn: aStream. aStream nextPut: $,. imagpart printOn: aStream. aStream nextPut: $) ! ! |
There should be surprisingly little which is actually
new in this example. The printing method uses both printOn:
as well as nextPut: to do its printing. While we haven't
covered it, it's pretty clear that $(
generates the ASCII
character (
as an object, and nextPut: puts its argument
as the next thing on the stream.
The math operations all generate a new object, calculating the real and imaginary parts, and invoking the Complex class to create the new object. Our creation code is a little more compact than earlier examples; instead of using a local variable to name the newly-created object, we just use the return value and send a message directly to the new object. Our initialization code explicitly returns self; what would happen if we left this off?
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
webmaster | delorie software privacy |
Copyright © 2003 by The Free Software Foundation | Updated Jun 2003 |