Я думаю, что важно отметить разницу между Smalltalk и другими языками OO.
В других языках OO у вас есть конструкция, называемая конструктором.Это позволяет вам автоматически запускать определенный код при вызове метода new
.
Например, в ruby вы должны сделать
# Class name
class ConstructorExample
# A constructor
def initialize
puts "I'm now running constructor"
end
end
# Creating Object
ConstructorExample.new # upon which calling you will get initialized run automatically.
Вывод будет вваша оболочка:
> I'm now running constructor
В Smalltalk вы должны различать new
и basicNew
.(Иногда даже new
является только псевдонимом для basicNew
, поэтому вам нужно запустить initialize
вручную или создать метод класса. basicNew
не выполняет инициализацию автоматически, обычно new
(не все диалекты!).
Приведенный выше пример можно записать в виде:
Object subclass:#ConstructorExample
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
category: ''
ConstructorExample>>initialize
Transcript showCR: 'I'm now running a constructor'
"You would then instantiate"
ConstructorExample new
или
| example |
example := ConstructorExample basicNew.
example initialize "sending method initialize like any other method"
В обоих случаях вывод будет (в вашей расшифровке):
I'm now running a constructor
Основной причиной этого, на мой взгляд, является то, что вы можете запускать конструктор после некоторого вашего пользовательского кода, если у вас есть метод класса
ConstructorExample class >> run
^ self basicNew; Transcript showCR: 'Running before constructor'; self initialize; yourself
Тогда вы просто сделаете:
ConstructorExample run
Вывод будет:
Running before constructor
I'm now running a constructor
Теперь к вашему примеру
As JayK , melkyades объяснил основные различия, которые я приведу более подробно (*):
Первый:
Rectangle new origin: 5@5 extent: 40@30
Что он на самом деле делает (без Transcript showCR:
)):
| myRactangle |
myRactangle := Ractangle new. "Creates an empty instance with origin: 0 @ 0 corner: 0 @ 0 and would execute initialize if there would be one."
Transcript showCR: 'Current origin: ', origin asString, 'with corner: ', corner asString. "You should see the zeros"
myRactangle origin: 5@5 extent: 40@30
Transcript showCR: 'Current origin: ', origin asString, 'with corner: ', corner asString. "You should your custom point(s)"
Что происходит, когда вы делаете Ractangle new
?
Rectangle class >> new [
"Answer the (0 @ 0 corner: 0 @ 0) rectangle"
<category: 'instance creation'>
^self origin: 0 @ 0 corner: 0 @ 0
]
Когда вы проверяете исходный код, он sets origin: 0 @ 0 corner: 0 @ 0
(обратите внимание нанастройка ifference с помощью ... corner:
, а не extent:
).
Секунда:
Rectangle origin: 5@5 extent: 40@30
Исходный код:
Rectangle class >> origin: originPoint extent: extentPoint
"Answer a rectangle with the given origin and size"
<category: 'instance creation'>
^self basicNew origin: originPoint corner: originPoint + extentPoint
Как указаноуже существует basicNew
, который запрещает запуск любого конструктора initialize
вручную или с помощью метода класса, как я показал выше.
Что вы могли бы сделать, переписать его, если вам нужно.Вы должны создать свой собственный класс прямоугольника, который унаследует его от Rectangle, и переписать его там.
Например:
Rectangle subclass:#ApplicationRectangle
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
category: ''
, где вы бы определили:
ApplicationRectangle class >> origin: originPoint extent: extentPoint
"Answer a rectangle with the given origin and size"
<category: 'instance creation'>
^self new origin: originPoint corner: originPoint + extentPoint
Затем вы бы назвали его:
ApplicationRectangle origin: 5@5 extent: 40@30