Sign in to follow this  
PDHB

[.net] Untitled

Recommended Posts

suppose I have Class Doggy : Animal and Class DoggyTeeth : AnimalTeeth Animal has a member function public virtual AnimalTeeth Animal.FindTeethStuff()... I want to override this in Doggy, but I want it to return a DoggyTeeth object. What's the proper way to do this ? Option 1: public override Doggy.AnimalTeeth FindTeethSTuff() { return (DoggyTeeth) base.FindTeethSTuff() } Option 2: public new DoggyTeeth FindTeethStuff() { return (DoggyTeeth) base.FindTeethSTuff() } in option 2, of course, Animal.FindTeethStuff() need no longer be virtual. Option 3: another way Option 4: don't try this. I'm being a bad programmer.

Share this post


Link to post
Share on other sites
Ok, you probably want to stay away from the new modifier unless you know what you are doing. It is for hiding and I don't thnk that that is waht you want to be doing here. When you override a method the signature needs to be the same so casting within the method body is useless. If you want to get a different type out you should just use a differen method name: FindDoggyTeeth() or cast outside of the method call: DoggyTeeth t = (DoggyTeeth)doggy.FindTeethStuff().

If you don't know that the object you have is a specific subtype of some type than you cannot know that it will have some non specific interface. If you do know than there is no reason to use the same method signature except to induce confusion.

Your Doggy can implement FindTeethStuff to return a DoggyTeeth as a AnimalTeeth because a DoggyTeeth is an AnimalTeeth. This would only be useful in a context where you were not sure that the instance of the object was in fact a Doggy (could be a Cow) and DoggyTeeth behaved in some different way than CowTeeth.


//context where yon't know what animal is what.
//If you used a new modifier this would not work.
public static void MassBite(Animal[] animals){
foreach(Animal a in animals){
AnimalTeeth t = a.FindTeethStuff();
t.Bite();
}
}

//here we know it is a doggy:
public static void DogsOnlyBite(Animal[] animals){
foreach(Animal a in animals){
if(a is Doggy){
DoggyTeeth t = (DoggyTeeth)a.FindTeethStuff();
//OR: DoggyTeeth t = a.FindDoggyTeeth();
t.Bite();
}
}
}



Ok, all this is probably rather confusing. So I am going to choose...

Option 5: Re-evaluate what you are trying to do and clairify what problem you are trying to solve. Inheritance and overriding may not be the solution.

Sorry for going on like this. I hope something here helps you.
past.

Share this post


Link to post
Share on other sites
I agree with turnpast that you should clarify what you are trying to do. Without knowing that, I'll use a simple example of speaking to illustrate the point:


public class Animal
{
public virtual string Speak() {}
}

public class Dog : Animal
{
public override string Speak()
{
return "Arf, Arf!";
}
}

public class Cat : Animal
{
public override string Speak()
{
return "Meow";
}
}




I know this doesn't really show an example of what you want to do. So, let's re-architect it a bit. Let's say that we want the concept of an animal's voice to be seperate from the type of animal. This will allow us to do funky stuff like have a cat talk like a dog if necessary (for some funky gameplay mechanic I'm sure ;)). We can do this by off-loading the speaking to it's own class and having each derived animal class determine what voice it should speak with by default:


public abstract class AnimalVoice
{
public abstract string Speak();
}

public class DogVoice : AnimalVoice
{
public override string Speak() { return "Arf"; }
}

public class CatVoice : AnimalVoice
{
public override string Speak() { return "Meow"; }
}

public class Animal
{
protected AnimalVoice voice;

public string Speak()
{
return voice.Speak();
}
}

public class Dog : Animal
{
public Dog()
{
this.voice = new DogVoice();
}
}

public class Cat : Animal
{
public Cat()
{
this.voice = new CatVoice();
}
}




As you can see, there are numerous ways to "skin the cat" (pardon the pun). That's the beauty of software design and OOP. Until we know exactly what you are trying to do though, it's difficult to give you good advice on the "proper" way to do something.

I hope this helps!

Share this post


Link to post
Share on other sites
I think your post could be titled "No C# Covariance?"... Of course, C++ allows what you want, but they ditched this ability in C#. My solution to this problem was to keep the virtual signature with the return value in the base form instead of the derived. I haven't found any workaround yet, and it does bug me.

Share this post


Link to post
Share on other sites

public class AnimalTeeth {
}

public class DoggyTeeth : AnimalTeeth {
}

interface IAnimal {
AnimalTeeth GetTeeth();
}

public class Doggy : IAnimal {
AnimalTeeth IAnimal.GetTeeth() {
return GetTeeth();
}
public DoggyTeeth GetTeeth() {
//do stuff
}
}

Share this post


Link to post
Share on other sites
I'm making a library.

SystemTemplate is a member class of the library. SystemTemplate will always contain IElement members, and often IVariableElement members, where IVariableElement inherits from IElement.

I don't want the developer using the library to have to remember to cast IElement or IVariableElement whenever he calls an inherited function with these return types. First of all, it's a pain in the rear. Second, those who use this library will typically know C# or some other NET language, but only in the same sense that someone can speak Russian after a "Learn Russian in 21 days" course. I suppose I could include a tool that would generate an adapter that would do all the casting, but this might reduce flexibility more than I care to.

This is actually a simplification of what I'm doing, but that's the general idea.

Share this post


Link to post
Share on other sites
Some conversions are implicit, that is you don't have to cast:

class A {
B some_b;
public virtual B GetB(){
return some_b;
}
class B {
public virtual void DoSomething(){}
}
class C : A {
D some_d;
public override B GetB(){
return some_d;
}
class D : B {
public override void DoSomething(){}
}

C c = new C();
B b = c.getB();//actaully a D
b.DoSomething();



Should work fine.

Even if you could make C return a D (as a D) from GetB() you would not want to -- it would negate the benifits of inheritence. That is given some A (that could be a C) you could not safely call GetB(). Better to gave a GetD() method in C.

Sorry bout the confusing psudocode.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this