Can an object cast itself to a derived class?
-
This is 50% curiousity, 50% because I might want to do this (so if this is a 'DON'T DO THIS EVER' type thing, by all means tell me) but I don't even know if its possible. Say you had something like this: class Book; class CheckedOutBook : Book; class Library ..void CheckOut(ref Book b, Person p); Is it possible for CheckOut() to transform the book input into it so it is now a CheckedOutBook? Obviously, you can return a new instance of CheckedOutBook, but I'm specifically talking about transforming the reference - my memories of C++ are that with pointers it should certainly be possible, but is it in C#? To be clear I'm thinking of something like this: Book b = new Book("Design Patterns"); (new Library()).CheckOut(b, new Person("Frank")); Diagnostics.Assert(b is Book); Diagnostics.Assert(b is CheckedOutBook);
-
This is 50% curiousity, 50% because I might want to do this (so if this is a 'DON'T DO THIS EVER' type thing, by all means tell me) but I don't even know if its possible. Say you had something like this: class Book; class CheckedOutBook : Book; class Library ..void CheckOut(ref Book b, Person p); Is it possible for CheckOut() to transform the book input into it so it is now a CheckedOutBook? Obviously, you can return a new instance of CheckedOutBook, but I'm specifically talking about transforming the reference - my memories of C++ are that with pointers it should certainly be possible, but is it in C#? To be clear I'm thinking of something like this: Book b = new Book("Design Patterns"); (new Library()).CheckOut(b, new Person("Frank")); Diagnostics.Assert(b is Book); Diagnostics.Assert(b is CheckedOutBook);
Togakangaroo wrote:
This is 50% curiousity, 50% because I might want to do this (so if this is a 'DON'T DO THIS EVER' type thing, by all means tell me) but I don't even know if its possible.
Code in the base class can cast itself to a derived class IF (AND ONLY IF) the object is actually an instance of the derived class in the first place. HOWEVER, (and you're way ahead of me), this is a "DON'T DO THIS EVER" type of thing. The base class should have no knowledge of its derived classes. It is the responsibility of the derived class to know about its base. If a base class uses information about derived classes then you lock the base class effectively. The base is no longer open to extension by other new derived classes at a later date. Any new derived class would potentially require changes in the base. This is bad.
Togakangaroo wrote:
Is it possible for CheckOut() to transform the book input into it so it is now a CheckedOutBook?
This is a different question. CheckOut is a method on Library which is not in the same class heirarchy as Book and
CheckedOutBook
. You have aref Book b
in the method signature, so I suppose you could REPLACEb
with aCheckedOutBook
but not transform the existing one. Also I consider usingref
andout
to be poor practice. In an OO system there are many better ways to accomplish the same thing. I see that there is no return value for the method so there really is no reason at all to be usingref
as you can do that through the return value. Also, the implication ofCheckedOutBook
is that you are assigning state (whether the book is checked out or not) to the class. State should be a property of the class, not the reason d'etre of the class. I hope this helps.Recent blog posts: *SQL Server / Visual Studio install order *Installing SQL Server 2005 on Vista *Crazy Extension Methods Redux * Mixins My Blog
-
Togakangaroo wrote:
This is 50% curiousity, 50% because I might want to do this (so if this is a 'DON'T DO THIS EVER' type thing, by all means tell me) but I don't even know if its possible.
Code in the base class can cast itself to a derived class IF (AND ONLY IF) the object is actually an instance of the derived class in the first place. HOWEVER, (and you're way ahead of me), this is a "DON'T DO THIS EVER" type of thing. The base class should have no knowledge of its derived classes. It is the responsibility of the derived class to know about its base. If a base class uses information about derived classes then you lock the base class effectively. The base is no longer open to extension by other new derived classes at a later date. Any new derived class would potentially require changes in the base. This is bad.
Togakangaroo wrote:
Is it possible for CheckOut() to transform the book input into it so it is now a CheckedOutBook?
This is a different question. CheckOut is a method on Library which is not in the same class heirarchy as Book and
CheckedOutBook
. You have aref Book b
in the method signature, so I suppose you could REPLACEb
with aCheckedOutBook
but not transform the existing one. Also I consider usingref
andout
to be poor practice. In an OO system there are many better ways to accomplish the same thing. I see that there is no return value for the method so there really is no reason at all to be usingref
as you can do that through the return value. Also, the implication ofCheckedOutBook
is that you are assigning state (whether the book is checked out or not) to the class. State should be a property of the class, not the reason d'etre of the class. I hope this helps.Recent blog posts: *SQL Server / Visual Studio install order *Installing SQL Server 2005 on Vista *Crazy Extension Methods Redux * Mixins My Blog
Good point about not having a base class cast itself - As you pointed out, I guess in what I was saying CheckOut() would be what is doing the casting and really the only reason I would want to do this would be for fear of someone referring to the old variable later on in the scope. Obviously there are much better ways of preventing this. So let's move this entirely into the "I'm just curious" column.
-
This is 50% curiousity, 50% because I might want to do this (so if this is a 'DON'T DO THIS EVER' type thing, by all means tell me) but I don't even know if its possible. Say you had something like this: class Book; class CheckedOutBook : Book; class Library ..void CheckOut(ref Book b, Person p); Is it possible for CheckOut() to transform the book input into it so it is now a CheckedOutBook? Obviously, you can return a new instance of CheckedOutBook, but I'm specifically talking about transforming the reference - my memories of C++ are that with pointers it should certainly be possible, but is it in C#? To be clear I'm thinking of something like this: Book b = new Book("Design Patterns"); (new Library()).CheckOut(b, new Person("Frank")); Diagnostics.Assert(b is Book); Diagnostics.Assert(b is CheckedOutBook);
I agree with Colin for the most part. It seems as though you are looking to use the class itself as a way to represent some information about the instance. Although as you mentioned this can work in C++, C# works very differently, and the type of an object really represents two things: first of all, the actual type of the instance, and secondly (in the case of base classes) a common interface (since subclassing is really just a way of implementing the base class's interface, from the perspective of someone using the object). Anyhow, if you were to cast the instance of ref Book b to a CheckedOutBook inside CheckOut(), this would actually only apply to the local representation of b, and even though it's marked as ref, would not affect the object passed into it, namely because that object in the calling method already has an interpretation (type), and ref parameters allow an object to be changed, not how it is interpreted (i.e. its local apparent type). As far as it being a "DON'T DO THIS EVER" thing, I think you'll quickly realize that it won't work, so it's not so much a warning as there's just no point in doing it. Now that said, you might actually be able to do something like what you want by creating a new object of type CheckedOutBook, setting it as somehow equivalent to the passed-in Book, and then setting the ref b parameter to equal the new instance (since it is still a Book). The key is that you will have to create a new object, and the old one will still be floating around so long as it is used (elsewhere). However you appear to be aware of this scenario. The short answer is no, you cannot "transform" a reference to be some type other than how it was created. Not in C#.
“Time and space can be a bitch.” –Gushie, Quantum Leap {o,o}.oO( Looking for a great RSS reader? Try FeedBeast! ) |)””’) Built with home-grown CodeProject components! -”-”-