When programming C++ we used to create copy constructors when needed (or so we were taught). When switching to Java a few years ago, I noticed that the Cloneable interface is now being used instead. C# followed the same route defining the ICloneable interface. It seems to me that cloning is part of the definition of OOP. But I wonder, why were these interfaces created, and the copy constructor seems to have been dropped?
When I thought about it, I came to the thought that a copy constructor would not be useful if one needs to make a copy of an object whose type is not known (as in having a reference to a base type). This seems logical. But I wonder whether there are other reasons that I do not know of, for which the Cloneable interfaces have been favored over copy constructors?
I think it's because there is no such inherent need for a copy constructor in Java and in C# for reference types. In C++ objects are named. You can (and you will most often) copy (and in C++1x move) them around e.g when returning from functions, since returning pointers require you to allocate dynamic memory which would be slow and painful to manage. The syntax is T(x) so it makes sense to make a constructor taking a T reference. C++ couldn't make a clone function, since that would require returning an object by value again (and thus another copy).
But in Java, objects are unnamed. There are only references to them, which can be copied, but the object itself isn't copied. For the cases when you actually need to copy them, you can use the clone call (but i read in other anwers clone is flawed. i'm no java programmer so i cannot comment that). Since not the object itself is returned, but rather a reference to it, a clone function will suffice. Also a clone function can be overriden. That's not going to work with copy constructors. And incidentally, in C++ when you need to copy a polymorphic object, a clone function is required too. It's got a name, the so-called virtual copy constructor.
Because C++ and Java (and C#) aren't the same thing. C++ has no built-in interfaces because interfaces aren't part of the language. You can fake them with abstract classes but they aren't how you think about C++. Also, in C++ assignment is normally deep.
In Java and C# assignment just involves copying the handle to the internal object. Basically when you see:
SomeClass x = new SomeClass();
in Java or C#, there's a level of indirection builtin that doesn't exist in C++. In C++, you write:
SomeClass* x = new SomeClass();
Assignment in C++ involves the dereferenced value:
*x = *another_x;
In Java you can get access to the "real" object as there is no dereference operator like *x. So to do a deep copy, you need a function: clone(). And both Java and C# wrapped that function into an interface.
It's the issues of final type and of cascading the clone operation through the super classes which is not addressed by copy constructors - they are not extensible. But the Java clone mechanism is widely considered badly broken too; especially problems where a subclass does not implement clone(), but inherits from a superclass that implements cloneable.
I strongly recommend you research cloning carefully, whatever path you choose - you will likely choose the clone() option, but make sure you know exactly how to do it properly. It's rather like equals() and hashCode() - looks simple on the surface, but it has to be done exactly right.
I think you haven't get the right point. I give you my two cents.
Fundamentally there's a problem: creating a clone of a class without knowing the exact class type. If you use copy constructor, you cannot.
Here is an example:
class A {
public A(A c) { aMember = c.aMember }
int aMember;
}
class B : A {
public B(B c) : base(c) { bMember = c.bMember }
int bMember;
}
class GenericContainer {
public GenericContainer(GenericContainer c) {
// XXX Wrong code: if aBaseClass is an instance of B, the cloned member won't
// be a B instance!
aBaseClass = new A(c.aBaseClass);
}
A aBaseClass;
}
The Clone method, if declare virtual, could create the right class instance of the generic member.
An this problem is common to every language, C# C++ or Java...
Maybe this is what you was meaning, but I cannot understand this from any answer.
Just wanted to add that in Java the copy constructor is not completely useless.
There are cases where your class has a private instance variable of a mutable non-final type, e.g. Date, and has a setter and getter for the variable. In the setter, you should make a copy of the given date, because the caller could modify it later and thereby manipulate your object's internal state (usually by accident, but maybe intentional). In the getter, the same precaution is required.
The defensive copy could be implemented by calling clone() (the class Date is cloneable), but a malicious caller could call the setter with a subclass of Date which overrides the clone() method with {return this;}, and so the caller might still be able to manipulate your object. This is where the copy constructor comes into play: By calling new Date(theDate), you are sure to get a fresh Date instance with the same timestamp as the given date, without any connection between the two date instances. In the getter, you could use the clone method, because you know the private variable will be of class Date, but for consistency, usually the copy constructor is used there, too.
Also note that the copy constructor would note be required if the Date class was final (calling clone() were safe) or immutable (no copy required).
I think its only because once u have defined a copy constructor, you could never pass the reference itself again. (Unless it would have a function that does that...but thats not any easier than using the clone() method.)
In C++ its not a problem: you can pass the whole object or its reference.
Related
I have been getting Delphi compiler warnings about Method 'Create' hides virtual method of base.
I have reviewed several Stack Overflow links (see below), and I don't understand the logic behind this warning, and why it is considered bad coding practice. I'm hoping others can help me understand
I will include some sample code:
type
TMachine = class(TPersistent)
private
public
Horsepower : integer;
procedure Assign(Source : TMachine);
end;
...
procedure TMachine.Assign(Source : TMachine);
begin
inherited Assign(Source);
Self.Horsepower := Source.HorsePower;
end;
This causes the compiler warning.
[dcc32 Warning] Unit1.pas(21): W1010 Method 'Assign' hides virtual method of base type 'TPersistent'
I have been ignoring this warning because it didn't make any sense to me. But that got me in trouble in another way (see my other post here: Why does Delphi call incorrect constructor during dynamic object creation?) so I have decided to try to understand this better.
I know that if I use the reserved word reintroduce, the error will go away, but I have seen it repeatedly posted that this is a bad idea. As Warren P wrote here (Delphi: Method 'Create' hides virtual method of base - but it's right there), "IMHO, if you need reintroduce, your code smells horrible".
I think I understand what is meant by "hiding". As David Heffernan said here (What causes "W1010 Method '%s' hides virtual method of base type '%s'" warning?):
What is meant by hiding is that from the derived class you no longer have access to the virtual method declared in the base class. You cannot refer to it since it has the same name as the method declared in the derived class. And that latter method is the one that is visible from the derived class.
But I am somewhat confused because it seems that ancestor method is not really hidden, because a derived class can always just use the inherited keyword to call the method in the base class. So 'hidden' really means 'somewhat hidden'?
I think I also understand that using the reserved word override will prevent the compiler warning, but the procedure signature has to be the same (i.e. no newly added parameters). That I can't use that here.
What I don't understand is why hiding is something to be warned about. In my code example above, I would not want users of TMachine.Assign() to instead somehow use TPersistent.Assign(). In my extended class, I have extended needs, and therefore want to them to use the new and improved function. So it seems like hiding the older code is exactly what I want. My understanding of a virtual method is one where the correct method is called based on the actual type of an object at run time. I don't think that should have any bearing in this case.
Additional code, to be added to example code above
TAutomobile = class(TMachine)
public
NumOfDoors : integer;
constructor Create(NumOfDoors, AHorsepower : integer);
end;
...
constructor TAutomobile.Create(ANumOfDoors, AHorsepower : integer);
begin
Inherited Create(AHorsepower);
NumOfDoors := ANumOfDoors;
end;
This adds new compiler warning message: [dcc32 Warning] Unit1.pas(27): W1010 Method 'Create' hides virtual method of base type 'TMachine'
I especially don't understand problems that arise with using new constructors with additional parameters. In this post (SerialForms.pas(17): W1010 Method 'Create' hides virtual method of base type 'TComponent'), the wisdom seems to be that a constructor with a different name should be introduced, e.g. CreateWithSize. This would seem to allow users to pick and choose which constructor they want to use.
And if they choose the the old constructor the extended class might be missing some needed information for creation. But if, instead, I 'hide' the prior constructor, it is somehow bad programming. Marjan Venema wrote about reintroduce in this same link: Reintroduce breaks polymorphism. Which means that you can no longer use meta classes (TxxxClass = class of Tyyy) to instantiate your TComponent descendant as its Create won't be called. I don't understand this at all.
Perhaps I need to understand polymorphism better. Tony Stark wrote in this link (What is polymorphism, what is it for, and how is it used?) that polymorphism is: "the concept of object oriented programming.The ability of different objects to respond, each in its own way, to identical messages is called polymorphism." So am I presenting a different interface, i.e. no longer an identical message, and thus this breaks polymorphism?
What am I missing? In summary, isn't hiding base code a good thing in my examples?
The danger here is that you might call Assign on a base class reference. Because you did not use override then your derived class method is not called. You have thus subverted polymorphism.
By the principle of least surprise you should use override here, or give your derived class method a different name. The latter option is simple. The former looks like this:
type
TMachine = class(TPersistent)
public
Horsepower : integer;
procedure Assign(Source : TPersistent); override;
end;
...
procedure TMachine.Assign(Source : TPersistent);
begin
if Source is TMachine then begin
Horsepower := TMachine(Source).Horsepower;
end else begin
inherited Assign(Source);
end;
end;
This allows your class to co-operate with the polymorphic design of TPersistent. Without using override that would not be possible.
Your next example, with virtual constructors is similar. The entire point of making a constructor virtual is so that you can create instances without knowing their type until runtime. The canonical example is the streaming framework, the framework that processes .dfm/.fmx files and creates objects and sets their properties.
That streaming framework relies on the virtual constructor of TComponent:
constructor Create(AOwner: TComponent); virtual;
If you want a component to work with the streaming framework, you must override this constructor. If you hide it, then the streaming framework cannot find your constructor.
Consider how the streaming framework instantiates components. It does not know about all the component classes it needs to work with. It cannot, for instance consider third party code, the code you write. The Delphi RTL cannot know about types defined there. The streaming framework instantiates components like this:
type
TComponentClass = class of TComponent;
var
ClassName: string;
ClassType: TComponentClass;
NewComponent: TComponent;
....
ClassName := ...; // read class name from .dfm/.fmx file
ClassType := GetClass(ClassName); // a reference to the class to be instantiated
NewComponent := ClassType.Create(...); // instantiate the component
The ClassType variable holds a meta class. This allows us to represent a type which is not known until runtime. We need the call to Create to be dispatched polymorphically so that the code in the component's constructor is executed. Unless you use override when declaring that constructor, it won't be.
Really, all of this boils down to polymorphism. If your understanding of polymorphism is not firm, as you suggest, then you will struggle to appreciate any of this. I think your next move is to get a better grip on what polymorphism is.
There are different benefits for using inheritance. In your examples you do it to avoid coding the same things again and again. So if TMachine has Horsepower field already and some methods and now you need more advanced TAutomobile with NumOfDoors, you make it TMachine descendant.
If you now always treat them differently, i.e in some code you use exactly TMachine (machine := TMachine.Create(...), machine.Assign(AnotherMachine) etc. ) and in another code you use TAutomobile and they never get mixed
then you're all right, you can ignore these warnings or 'mute' them with reintroduce.
But there is usually another aspect of inheritance: keeping uniform interface, or as it's sometimes called: 'contract'. Separating interface from implementation.
For example, form is able to free all the objects which belong to it, no matter what these objects are, that's because of Destroy method which gets overrided. Form doesn't care about your implementation, but it knows: to free the object it just have to call Destroy, that easy. If you don't override Destroy, that's extremely bad: no way TForm will call you as TMachine.Destroy. It'll call you as TObject.Destroy, but it won't lead to your TMachine.Destroy, so you get a memory leak. In most cases when some method wasn't overriden it's just because programmer forgot to do it, thus a warning: it's very helpful one. If programmer didn't forget it but that was intentionally, reintroduce keyword is used. This way programmer tells: "Yes, I know what I do, this is intentionally, don't disturb me!"
TPersistent.Assign is another procedure which is frequently called from base class, not derived (that is: we don't want to pay attention to implementation, we just want to copy an object, whatever it is). For example, TMemo has Lines: TStrings, but TStrings is an abstract class, while the actual implementation is TStringList. So, when you write Memo1.Lines.Assign(Memo2.Lines), the TStrings.Assign method is used. It may implement this assign through another methods: clear itself first and then add line after line. Some TStrings descendant may want to speed-up process by some block copy of data. Of course it has to use exactly Assign(Source: TPersistent) method and override it, otherwise it is never called (inherited is called instead).
Classic implementation of Assign is like this:
procedure TMachine.Assign(Source : TPersistent);
begin
if Source is TMachine then
Horsepower := TMachine(Source).Horsepower
else inherited Assign(Source);
end;
That's the case when inherited shouldn't be called first thing. Here it is 'the last resort': it's called last if nothing else helped. It makes one final try: if your class don't know how to assign, maybe that Source knows how to AssignTo your class?
For example, TBitmap was coded long, long ago. After that TPngImage was developed to work with, well, PNG. You want to put PNG into bitmap and write: Bitmap.Assign(PngImage). No way TBitmap may know how to deal with PNG: it didn't exist back then! But TPngImage writer knew that may happen and implemented AssignTo method which is able to convert it to bitmap. So TBitmap as the last straw calls TPersistent.Assign method and that in turn calls TPngImage.AssignTo and that works like a charm.
Is this side of inheritance needed in your program is up to you. If there is again lots of dublicating code (the one which deals with machines and another with automobiles) or there are lots of conditions, then something is wrong and some good polymorphism might be of help.
Is it true that for C++ to work similarly in terms of modern OOP as in Java, Ruby, Python, the function (or methods) must be declared virtual and if not, what "strange" behaviors may occur?
I think it is true that for Java, Ruby, Python, and possibly other OOP languages that are late comers such as PHP and Lua, and even Smalltalk and Objective-C, all methods are just what is known as "virtual functions"?
"Method" is an unfortunately overloaded term that can mean many things. There's a reason C++ prefers different terminology, and that's because not only does it do something different from other languages, but it intends to do something different from what other languages do.
In C++ you call a member function. i.e. you externally make a call to a function associated with an object. Whether that function is virtual or not is secondary; what matters is the intended ordering of your actions - you're reaching into the object's scope, and commanding it to take a specific action. It might be that the object can specialize the action, but if so, it warned you in advance that it would do this.
In Smalltalk and the languages that imitate it (Objective-C most closely), you send a message to an object. A message is constructed on your side of the call consisting of a task name (i.e. method selector), arguments, etc., and the packed up and sent to the object, for the object to deal with as it sees fit. Semantically, it's entirely the object's decision what to do upon receipt of the message - it can examine the task name and decide which implementation to apply dynamically, according to a user-implemented choice process, or even do nothing at all. The outside calling code doesn't get to say what the object will do, and certainly doesn't get any say in which procedure actually runs.
Some languages fall in the middle ground, e.g. Java is inspired by the latter, but doesn't give the user any way to specify unusual dynamic responses - for the sake of simplicity every message does result in a call, but which call is still hidden from the external code, because it's entirely the object's business. C++ was never built on this philosophy of messages in the first place, so it has a different default assumption about how its member functions should operate.
The thing is that C++ is like the great grand father. It has many features, which often requires huge code definition.
Consider an example:
class A
{
virtual void fn() = 0;
};
class B: A
{
void fn();
};
#include "a.hpp"
#include "b.hpp"
int main()
{
A *a = new B();
a->fn();
}
This would implement overriding in C++.
Note that virtual void fn()=0 makes the class A abstract, and a pointer to base class (A) is essential.
In Java, the process is even simpler
abstract class A
{
abstract void fn();
}
class B extends A
{
void fn() {
//Some insane function :)
}
}
public static void main(String[] args) {
B ob = new B();
ob.fn();
}
Well, the effect is same; but the process is largely different. In short, C++ does have many features implemented in languages like Java, Ruby etc. but it is simply implemented using some (often complicated) techniques.
Regarding Php, since it is directly based on C++, there exists some syntax similarities between C++ and Php.
It is true that (for example) in Java all methods are virtual by default. In C++ it is possible to overload a non-virtual function (as opposed to overriding a virtual function) in a subclass, leading to possible counter-intutive behaviour, when only the base function is actually executed via a pointer or reference to the base class (i.e. when polymorphic behavior would normally be expected).
Because C++ is a value-based (as opposed to reference-based) language, then even when a function has been declared as virtual, the well known
object slicing problem can still arise: the superclass method is invoked when the type of a value object of a subclass is `cut down' to that of the base class (e.g. when the subclass is passed to a function which takes a base class argument by value).
For this reason, it is recommended to make all non-leaf classes abstract, something which is often achieved by providing a virtual destructor, even if such would otherwise be gratuitous.
I've been battling with AS3 for a little while now, and I'm working on a simple application using only actionscript and the FlashDevelop/flex-compiler combo. I've hit a bit of a wall in my fledgling OOP understanding, and I'm wondering whether someone might be able to point me in the right direction. I have genuinely read several books, and spent many hours reading online tutorials etc, but something's just not clicking!
What's baffling me is this: When something is declared 'public', according to what I read, it is therefore available anywhere in the application (and should therfore be used with care!) However, when I try to use public properties and methods in my program, they most definitely are not available anywhere other than from the class/object that instantiated them.
This leads me to conclude that even if objects (of different class) are instantiated from the same (say 'main') class, they are not able to communicate with each other at all, even through public members.
If so, then fair enough, but I've honestly not seen this explained properly anywhere. More to the point, how do different objects communicate with other then? and what does Public actually mean then, if it only works through a direct composition hierarchy? If one has to write applications based only on communication from composer class to it's own objects (and presumably use events for, er, everything else?) - isn't this incredibly restrictive?
I'm sure this is basic OOP stuff, so my apologies in advance!
Any quick tips or links would be massively appreciated.
There are different topics you are covering in your question. Let me clarify:
What does the modifier public mean?
How can instances of the same class communicate to each other?
--
1.
In OOP you organize your code with objects. An object needs to be instantiated to provide its functionality. The place where you instantiate the object can be considered as the "context". In Flash the context might be the first frame, in a pure AS3 movie, it might be the main class, in Flex it could be the main mxml file. In fact, the context is always an object, too. Class modifier of your object public class MyClass tells your context whether it is allowed to instantiate the object or not. If set to internal, the context must live in the same directory as the class of the object. Otherwise it is not allowed to create a new object of the class. Private or protected are not valid class modifiers. Public class ... means that any context may create an object of that class. Next: Not only instantiation is controlled by these modifiers but also the visibility of a type. If set to internal, you cannot use an expression like var obj : InternalType in a context that does not live in the same directory as Internal type.
What about methods and properties? Even if your context is allowed to access a type, certain properties and methods might be restricted internal/protected/private var/method and you perhaps are not able to invoke them.
Why we're having such restrictions? Answer is simple: Differnent developers may develop different parts of the same software. These parts should communicate only over defined interfaces. These interfaces should be as small as possible. The developer therefore declares as much code as possible to be hidden from outside and only the necessary types and properties publicly available.
Don't mix up with modifiers and global properties. The modifier only tells you if a context is allowed to see a type or method. The global variable is available throughout the code. So even if a class is declared to be public, instances of that class do not know each other by default. You can let them know by:
storing the instances in global variables
providing setter such as set obj1(obj1 : OBJ1) : void where each object needs to store the reference in an instance variable
passing the object as method arguments: doSomething(obj1 : OBJ1)
Hope this helps you to more understand OOP. I am happy to answer your follow up questions.
Jens
#Jens answer (disclaimer: I skimmed) appears to be completely correct.
However, I'm not sure it answers your question very directly, so I'll add a bit here.
A public property is a property of that class instance that is available for other objects to use(function: call, variable: access, etc). However, to use them you must have a reference (like a very basic pointer, if that helps?) to that object instance. The object that instantiates (creates, new ...) that object can take that reference by assigning it to a variable of that class type.
// Reference is now stored in 's'
public ExampleClass s = new ExampleClass();
If you'd like to, you do have the option of making a static property, which is available just by knowing the class name. That property will be shared by all instances of that class, and any external class can refer to it (assuming it's public static) by referring to the class name.
A public property is referred to by the reference you stored.
//public property access
s.foo
s.bar(var)
A static property is referred to by the class name.
//static property access
ExampleClass.foo
ExampleClass.bar(var)
Once you've created the instance, and stored the reference, to an object, you can pass it around as you'd like. The below object of type OtherExampleClass would receive the reference to 's' in its constructor, and would have to store it in a local variable of its own to keep the reference.
public OtherExampleClass s2 = new OtherExampleClass(s);
I'm trying to locate examples of assignment operators and copy constructors in C++/CLI. I have spent a lot of time on Google and surprisingly I can't find a decent example of something that seems pretty common.
.NET semantics have no such thing as a copy constructor or assignment operator. You can define one in your ref classes, but it will be used only in the C++ side if you request explicitly a copy` For value classes, everything is builtin and you cannot override copy semantics.
Example:
public ref class Foo
{
Foo(const Foo% f);
};
Foo^ f = gcnew Foo;
Foo^ g = gcnew Foo(*f); // This will call C++ copy constructor. No .NET equivalent.
Look at ICloneable if you want to implement deep copy semantics in the .NET style.
Also look there to get the different copy behaviors you can have. I'd strongly advice against storing ref classes on the stack though.
I'm reading about constructors,
When an object is instantiated for a class, c'tors (if explicitly written or a default one) are the starting points for execution. My doubts are
is a c'tor more like the main() in
C
Yes i understand the point that you
can set all the default values using
c'tor. I can also emulate the behavior
by writing a custom method. Then why a c'tor?
Example:
//The code below is written in C#.
public class Manipulate
{
public static int Main(string[] args) {
Provide provide = new Provide();
provide.Number(8);
provide.Square();
Console.ReadKey();
return 0;
}
}
public class Provide {
uint num;
public void Number(uint number)
{
num = number;
}
public void Square()
{
num *= num;
Console.WriteLine("{0}", num);
}
}
Am learning to program independently, so I'm depending on programming communities, can you also suggest me a good OOP's resource to get a better understanding. If am off topic please excuse me.
Head First OOA&D will be a good start.
Dont you feel calling a function for setting each and every member variable of your class is a bit overhead.
With a constructor you can initialize all your member variables at one go. Isnt this reason enough for you to have constructors.
Constructor and Destructor functionality may be emulated using regular methods. However, what makes those two type of methods unique is that the language treats them in a special way.
They are automatically called when an object is created or destroyed. This presents a uniform means to handle the most delicate operations that must take place during those two critical periods of an object's lifetime. It takes out the possibility of an end user of a class forgetting to call those at the appropriate times.
Furthermore, advanced OO features such as inheritance require that uniformity to even work.
First of all, most answers will depend at least a bit on the language you're using. Reasons that make great sense in one language don't necessarily have direct analogs in other languages. Just for example, in C++ there are quite a few situations where temporary objects are created automatically. The ctor is invoked as part of that process, but for most practical purposes it's impossible to explicitly invoke other member functions in the process. That doesn't necessarily apply to other OO languages though -- some won't create temporary objects implicitly at all.
Generally you should do all your initialization in the constructor. The constructor is the first thing called when an instance of your class is created, so you should setup any defaults here.
I think a good way to learn is comparing OOP between languages, it's like seeing the same picture from diferent angles.
Googling a while:
java (I prefer this, it's simple and full)- http://java.sun.com/docs/books/tutorial/java/concepts/
python - http://www.devshed.com/c/a/Python/Object-Oriented-Programming-With-Python-part-1/
c# - http://cplus.about.com/od/learnc/ss/csharpclasses.htm
Why constructors?
The main diference between a simple function (that also could have functions inside) and an Object, is the way that an Object can be hosted inside a "variable", with all it functions inside, and that also can react completly diferent to an other "variable" with the same kind of "object" inside. The way to make them have the same structure with diferent behaviours depends on the arguments you gave to the class.
So here's a lazy example:
car() is now a class.
c1 = car()
c2 = car()
¿c1 is exactly c2? Yes.
c1 = car(volkswagen)
c2 = car(lamborghini)
C1 has the same functionalities than C2, but they are completly diferent kinds of car()
Variables volkswagen and lamborghini were passed directly to the constructor.
Why a -constructor-? why not any other function? The answer is: order.
That's my best shot, man, for this late hours. I hope i've helped somehow.
You can't emulate the constructor in a custom method as the custom method is not called when the object is created. Only the constructor is called. Well, of course you can then call your custom method after you create the object, but this is not convention and other people using your object will not know to do this.
A constructor is just a convention that is agreed upon as a way to setup your object once it is created.
One of the reasons we need constructor is 'encapsulation',the code do something initialization must invisible
You also can't force the passing of variables without using a constructor. If you only want to instantiate an object if you have say an int to pass to it, you can set the default constructor as private, and make your constructor take an int. This way, it's impossible to create an object of that class without having it take an int.
Sub-objects will be initialized in the constructor. In languages like C++, where sub-objects exist within the containing object (instead of as separate objects connected via pointers or handles), the constructor is your only chance to pass parameters to sub-object constructors. Even in Java and C#, any base class is directly contained, so parameters to its constructor must be provided by your constructor.
Lastly, any constant (or in C#, readonly) member variables can only be set from the constructor. Even helper functions called from the constructor are unable to change them.