Casting up to inheriting class from base?

B

Brett Romero

Say I have a class inheriting some base class:

BaseClass
{
void Foo()
{
Update();
}
}


Class1 : BaseClass
{
void Update(){}
}


How can I have the base class know which instance class has inherited
it and use a method in the instance class? Only certain types of
classes will use the base and those classes will always have an
Update() method.

Thanks,
Brett
 
B

Brett Romero

One way of doing this is to use an interface implemented in the
inheriting class. In the base, do this:

(( IMyClass )this).Update();

I'm interested in any better methods.

Thanks,
Brett
 
B

Bruce Wood

Brett said:
Say I have a class inheriting some base class:

BaseClass
{
void Foo()
{
Update();
}
}


Class1 : BaseClass
{
void Update(){}
}


How can I have the base class know which instance class has inherited
it and use a method in the instance class? Only certain types of
classes will use the base and those classes will always have an
Update() method.

Maybe I'm missing something, but why can't you just make the base class
abstract, like this:

abstract BaseClass
{
void Foo()
{
Update();
}

abstract void Update()
{ ... }
}

?
 
J

John Duval

Hi Brett,
I am curious why you have Foo( ) in BaseClass if Update( ) might not
exist to be called? Would it just make more sense to put Foo( ) in the
subclass? It seems like you might want to reconsider your design --
otherwise you are getting into "downcasting" (casting from a baseclass
to a derived class). Usually when I run into that, I take it as a hint
that it's time to refactor the code...

Also, what will Foo( ) do if it determines that the derived class does
not implement Update( ) ? If it just does nothing, then maybe you
should have a virtual Update( ) in the BaseClass that simply does
nothing, then override that function in the subclass.

Not that I'm recommending this, but to answer your question you can
always use the "is" keyword to check what type you're dealing with.
For example:

class Base
{
public void Foo()
{
if (this is Derived)
{
Derived d = (Derived)this;
d.Update();
}
}
}

class Derived : Base
{
public void Update()
{
Console.WriteLine("I am derived");
}
}

class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
d.Foo(); // prints "I am derived"

Base b = new Base();
b.Foo(); // prints nothing
}
}

Hope that helps,
John
 
M

Mark Wilden

Brett Romero said:
Say I have a class inheriting some base class:

BaseClass
{
void Foo()
{
Update();
}
}


Class1 : BaseClass
{
void Update(){}
}


How can I have the base class know which instance class has inherited
it and use a method in the instance class? Only certain types of
classes will use the base and those classes will always have an
Update() method.

It's hard for me to say for sure (since "instance class" isn't really
correct - do you mean "derived class"?), but it's possible you just want to
make Foo() virtual.

///ark
 
B

Brett Romero

I am curious why you have Foo( ) in BaseClass if Update( ) might not
exist to be called?

Update() will always exist.


John, I don't know what the type will be so this code doesn't work:

public void Foo()
{
if (this is Derived)
{
Derived d = (Derived)this;
d.Update();
}
}

I was trying to provide a simple example but the code does this:

public class BaseClass<T>{...}

public class MyClass: BaseClass<Person>, IClass<Person>{...}

I guess I'm not sure how your code would apply in this case.

In the end, how is your technique any better tham what I'm doing? We
are both still casting.



I can't use abstract because the base class has method bodies that do
something. In other words, it isn't an abstract class.


Thanks,
Brett
 
T

Tom Spink

Brett said:
exist to be called?

Update() will always exist.


John, I don't know what the type will be so this code doesn't work:

public void Foo()
{
if (this is Derived)
{
Derived d = (Derived)this;
d.Update();
}
}

I was trying to provide a simple example but the code does this:

public class BaseClass<T>{...}

public class MyClass: BaseClass<Person>, IClass<Person>{...}

I guess I'm not sure how your code would apply in this case.

In the end, how is your technique any better tham what I'm doing? We
are both still casting.



I can't use abstract because the base class has method bodies that do
something. In other words, it isn't an abstract class.


Thanks,
Brett

Hi Brett,
Update() will always exist.

I know you say that, but the compiler doesn't know that. It is conceivable
that you could create a derived class that does not implement an Update()
method. You need to instruct the compilre that Update() will always exist.

To do this, you define your base class as being abstract, and your Update()
method as abstract:

public abstract class BaseClass
{
public void Foo()
{
Update();
}

public abstract void Update();
}

An abstract class cannot be instantiated, however, and if you require this
functionality, remove the abstract modifiers, and define the Update()
method as virtual, and in your base class, provide no implementation:

public class BaseClass
{
public void Foo()
{
Update();
}

public virtual void Update()
{
}
}

Now, any derived classes from the abstract version MUST override Update():

public class DerivedClass : BaseClass
{
public override void Update()
{
// Implementation
}
}

Or, derived classes from the virtual version MAY override Update():

public class DerivedClass : BaseClass
{
public override void Update()
{
// Implementation
}
}
 
B

Bruce Wood

Brett said:
I can't use abstract because the base class has method bodies that do
something. In other words, it isn't an abstract class.

You are mistaken as to what an abstract class is.

An abstract class can have methods and properties that do things, just
like a normal class. The only thing that makes it abstract is that
there is _at least one_ method / property / event / etc. that isn't
defined in the class and so must be defined in child classes.

The only reason that you couldn't have BaseClass be abstract is if
there is some situation in which you have to instantiate a base class
instance. If all you ever want is child class instances then BaseClass
can be abstract.
 
J

John Duval

Hi Brett,
I guess I don't understand your question. The way your original sample
was written, it would not compile because Update( ) is not available to
the base class. From your original post,
How can I have the base class know which instance class has inherited
it and use a method in the instance class? Only certain types of
classes will use the base and those classes will always have an
Update() method.

I thought you wanted a way to figure out which subclasses had the
Update( ) method that could be called, and in a way that the code would
compile. And I assumed you didn't want to add Update( ) to the base
class for some reason (although, as others have pointed out, making
this a virtual or abstract member would also solve your problem).

As for the "we're both still casting" question. Well, of course --
there is no way around it. If the Update( ) member does not exist in
the base class, you're going to need a different type to perform the
call. The only difference is that my sample will not attempt to cast
if the derived type doesn't have the Update( ) member (no runtime
error).

Since you say that Update( ) will always exist, I think I agree with
the other comments here that it should be an abstract or virtual method
in the base class.

Best,
John
 
B

Brett Romero

I went with making the class abstract and certain methods in the class
abstract (those that were in the interface). I've completely dropped
the interface and all is working fine. All of the casting has gone
away as well.

Thanks all.
Brett
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top