I have a class of mine, lets call it TMyObject, which should return a slightly modified copy of itself. So, one of its functions should return an object of the same type as itself:
function TMyObject.TrimEnds: TMyObject;
begin
Result:= TMyObject.Create;
Result.DoStuff;
edn;
Can I do that? Is it legit what am I doing?
I mean, I already tried it and the compiler allows me to do it, but I wonder if there will be long time/hidden negative effects.
Any thoughts will be appreciated. Thanks.
Edit: The new slightly modified copy will be saved to disk. It is some kind of 'Save as...'. How it works: The original object creates a copy of itself, instructs this copy to d开发者_如何学Pythono some changes and to save to disk. Then the original frees the copy. This way I keep the original object in memory unchanged but I have a modified version of this to disk.
You may think that my object holds a picture. What I need is a function that returns a slightly modified copy of the picture.
but I wonder if there will be long time/hidden negative effects.
I don't see any, and I used to do this with my own linked lists, and never had any problem. I think it is pretty much the same as creating an instance in any other place.
I guess you are right, this piece of code seems wrong to me. You always have to make it clear who's responsible for freeing the object you return. In most cases, this object will not be freed.
A better approach is to usually let the caller create the object, pass it to your method (you only need a procedure then) which modifies it.
I am curious to know why you would want to return a "slightly modified version" of your object. It sounds counter-intuitive to me...
As others had said, there's nothing wrong with that but there may be better ways.
Variant 1: Change this into class method and give it a meaningful name.
class function TMyObject.CreateSpecialized: TMyObject;
begin
Result := TMyObject.Create;
//initialize Result
end;
anObj := TMyObject.CreateSpecialized;
Variant 2: Use a constructor. You can have multiple constructors in a class.
constructor TMyObject.CreateSpecialized;
begin
Create; // make sure everything is initialized correctly
// now do custom initialization
end;
anObj := TMyObject.CreateSpecialized;
Usage is same in both examples but in second case your intentions are clearer to a random reader.
If you want to take one object and create another one based on first object's fields, use a constructor with parameter.
constructor TMyObject.CreateSpecialized(obj: TMyObject);
begin
Create;
intField := obj.IntField * 2;
end;
anObj := TMyObject.CreateSpecialized(otherObj);
If you have a new class derived from TMyObject like TMyOtherObject = class(TMyObject)
, the TrimEnds function will still return a TMyObject instead of a TMyOtherObject as one might expect.
You can fix this by using this scheme:
TMyObjectClass = class of TMyObject;
function TMyObject.TrimEnds: TMyObject;
begin
Result:= TMyObjectClass(ClassType).Create;
Result.DoStuff;
end;
there is absolutely nothing wrong with what you wrote. you are simply returning an object and this is perfectly valid, it could be any other object of any other type.
精彩评论