views:

1586

answers:

12

I'm not sure if this is a strange thing to do or not, or if it is some how code smell...but I was wondering if there was a way (some sort of oop pattern would be nice) to "cast" a base type to a form of its derived type. I know this makes little sense as the derived type will have additional functionality that the parent doesn't offer which is in its self not fundamentally sound. But is there some way to do this? Here is a code example to so I can better explain what I"m asking.

public class SomeBaseClass {
    public string GetBaseClassName {get;set;}
    public bool BooleanEvaluator {get;set;}
}

public class SomeDerivedClass : SomeBaseClass {
    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    SomeBaseClass class = new SomeBaseClass();
    SomeDerivedClass derClass = (SomeDerivedClass)class; 
    derClass.Insert(new sqlConnection);
}

I know this seems goofy but is there any way to accomplish something of this sort?

+7  A: 

Not soundly, in "managed" languages. This is downcasting, and there is no sane down way to handle it, for exactly the reason you described (subclasses provide more than base classes - where does this "more" come from?). If you really want a similar behaviour for a particular hierarchy, you could use constructors for derived types that will take the base type as a prototype.

One could build something with reflection that handled the simple cases (more specific types that have no addition state). In general, just redesign to avoid the problem.

Edit: Woops, can't write conversion operators between base/derived types. An oddity of Microsoft trying to "protect you" against yourself. Ah well, at least they're no where near as bad as Sun.

Adam Wright
You cant use casting/conversion operators for this case.
leppie
A: 

That cant work :) Go look at the help page linked by the compile error.

The best solution is to use factory methods here.

leppie
Lol...I know I was trying to get my thought process across...believe me I tried :D
Adam Driscoll
Adam Wright explains it better :)
leppie
A: 

This is called downcasting and Seldaek's suggestion to use the "safe" version is sound.

Here's a pretty decent description with code samples.

Ben Hoffstein
A: 

Downcasting makes sense, if you have an Object of derived class but it's referenced by a reference of base class type and for some reason You want it back to be referenced by a derived class type reference. In other words You can downcast to reverse the effect of previous upcasting. But You can't have an object of base class referenced by a reference of a derived class type.

Maciej Hehl
+1  A: 

No, this is not possible. In a managed language like C#, it just won't work. The runtime won't allow it, even if the compiler lets it through.

You said yourself that this seems goofy:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;

So ask yourself, is class actually an instance of SomeDerivedClass? No, so the conversion makes no sense. If you need to convert SomeBaseClass to SomeDerivedClass, then you should provide some kind of conversion, either a constructor or a conversion method.

It sounds as if your class hierarchy needs some work, though. In general, it shouldn't be possible to convert a base class instance into a derived class instance. There should generally be data and/or functionality that do not apply to the base class. If the derived class functionality applies to all instances of the base class, then it should either be rolled up into the base class or pulled into a new class that is not part of the base class hierarchy.

Derek Park
A: 

This will work:

SomeBaseClass class = new SomeDerivedClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;

Although this example is not too interesting, there are cases when this is useful.

Metro.

Metro
A: 

This is not possible because how are you going to get the "extra" that the derived class has. How would the compiler know that you mean derivedClass1 and not derivedClass2 when you instantiate it?

I think what you are really looking for is the factory pattern or similar so you can instantiate objects without really knowing the explicit type that's being instantiate. In your example, having the "Insert" method would be an interface that instance the factory returns implements.

Laplie
A: 

Yes - this is a code smell, and pretty much nails down the fact that your inheritance chain is broken.

My guess (from the limited sample) is that you'd rather have DerivedClass operate on an instance of SomeBaseClass - so that "DerivedClass has a SomeBaseClass", rather than "DerivedClass is a SomeBaseClass". This is known as "favor composition over inheritance".

Mark Brackett
+3  A: 

Try composition instead of inheritance!

It seems to me like you'd be better off passing an instance of SomeBaseClass to the SomeDerivedClass (which will no longer derive base class, and should be renamed as such)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Check out http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (page 3):

Code reuse via composition Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit.

Rob Fonseca-Ensor
Though I do favor composition over inheritance, the idea that "Apple has a fruit" rather than "Apple is a fruit" is about the worst example I've ever seen for it. If Apple defines it's own Peel method, then it's no longer substitutable for Fruit - which kind of borks the whole concept of Fruit.
Mark Brackett
+1  A: 

As others have noted, the casting you suggest is not really possible. Would it maybe be a case where the Decorator pattern(Head First extract) can be introduced?

borisCallens
A: 

Have you thought about an interface that what is currently your base class and your derived class both would implement? I don't know the specifics of why you're implementing this way but it might work.

marr75
A: 

I dont know why no one has said this and i may have miss something but you can use the as keyword and if you need to do an if statement use if.

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

-edit- I asked this question long ago

acidzombie24