[.net] Untitled

Started by
5 comments, last by turnpast 19 years, 5 months ago
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.
Behold the nascent power of Semejant!
Advertisement
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.
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!
Jason Olson - Software Developer[ Managed World ]
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.
	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		}	}

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

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.
Behold the nascent power of Semejant!
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 Db.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.

This topic is closed to new replies.

Advertisement