This is what a copy constructor would look like in Dyalog APL:
Code: Select all
:Class MyClass
:field private MyField1
:field private MyField2
:field private MyField3
∇ MyClass(MyClass_) ⍝ copy constructor
:Implements constructor
:Access public
:If (⎕CLASS MyClass_)≡⎕CLASS ⎕THIS
(MyField1 MyField2 MyField3)←MyClass_.(MyField1 MyField2 MyField3)
:EndIf
∇
∇ MyClass_ ⍝ default constructor
:Implements constructor
:Access public
∇
:property Field1
:access public
∇ r←get x
r←MyField1
∇
:endproperty
:property Field2
:access public
∇ r←get x
r←MyField2
∇
:endproperty
:property Field3
:access public
∇ r←get x
r←MyField3
∇
:endproperty
:EndClass
Notice that the constructor's argument is a reference to an object of its class just like in C++. The problem is that unless MyField1 - 3 are not public or have public property get methods this code will fail.
Additionally we spoke about when this code would be triggered.
Code: Select all
x←⎕NEW #.MyClass
y←⎕COPY x
was my line of reasoning, Morten preferred using some new primitive, but alas ⎕NEW then by definition should also use a new primitive.
So what happens if you don't define a copy constructor? Follow the same rules as C++:
Unless you explicitly declare one, the compiler gives every class a default copy constructor that implements member-wise copy. The only time you need to write a copy constructor is if your class contains pointer members and you need to take "deep" copies (ie, replicate not the pointer, but rather what is being pointed to).
If this is the case then the match primitive should indeed have performed a shallow match on each field in its arguments if they were classes. A deep match can be elegantly defined by overloading the match primitive in the class definition for its arguments and then invoked like:
Code: Select all
MyObj1.≡MyObj2
N.B. the dot notation in the above expression.