[.net] inheritance ?

Started by
6 comments, last by bilsa 17 years, 6 months ago
Hello! I was wondering if there is any way of doing the following in c# :

interface BaseObj {}

interface Base {
  BaseObj getObj();
}

class DerivedObj : Base {}

class Derived : Base {
  public DerivedObj getObj() {//...}

  public void doSomething(BaseObj base) {}
  public void doSomething(DerivedObj derived) {}
}


I mean, why can't I let getObj() return DerivedObj instead of BaseObj?? I mean, it should be implicitly cast to a BaseObj? This works in java. I would rather not have to add another function getDerivedObj(), thats just plain ugly :(
Advertisement
linky.
Quote:Original post by bilsa
Hello!

I was wondering if there is any way of doing the following in c# :

*** Source Snippet Removed ***

I mean, why can't I let getObj() return DerivedObj instead of BaseObj?? I mean, it should be implicitly cast to a BaseObj?

This works in java.

I would rather not have to add another function getDerivedObj(), thats just plain ugly :(

If you're targetting 2.0:
interface BaseObj {}interface Base<T> where T : BaseObj {  T getObj();}class DerivedObj : BaseObj {}class Derived : Base<DerivedObj> {  public DerivedObj getObj() {/*...*/}  public void doSomething(BaseObj base) {}  public void doSomething(DerivedObj derived) {}}

This isn't an ideal solution, but it will do the trick in many situations. It does have the unfortunate side effect of forcing you to make any code that relies on a Base object instead of a Derived object become generic:
   public int calculateSomething<T>(Base<T> obj) where T : BaseObj {}

One alternative, of course, is just to accept the cast:
class Derived : Base {  public BaseObj getObj() {return new DerivedObj();}  public void doSomething(BaseObj base) {}  public void doSomething(DerivedObj derived) {}}//later:Derived blah;DerivedObj blahObj = (DerivedObj)blah.getObj();

CM
Thx, this was what I found out to be the closest:

interface BaseObj {}interface Base {  BaseObj getObj();}class DerivedObj : Base {}class Derived : Base {  BaseObj Base.getObj() { return getObj(); }  public DerivedObj getObj() {//...}  public void doSomething(BaseObj base) {}  public void doSomething(DerivedObj derived) {}}


Of course that gets a bit annoying when new classes are added and maybe some performance loss.
Why do you want to do that? If it's a non-virtual method it should be fine (just creates a new method). If it's virtual, then from where you're calling it you shouldn't rely on the fact that you're dealing with a DerivedObj. This looks like a symptom of bad design to me.
Well, I'm not sure if it's bad design or not, but anyway... Here I will show you what it's for:

interface BaseIterator{}interface BaseCollection {    BaseIterator Iterator { get; } }interface MyReallyCoolIterator : BaseIterator{}interface SomeDerivedCollection : BaseCollection{    new MyReallyCoolIterator Iterator { get; }}


Why should I be bound to the abstract BaseIterator just because, I implement the BaseCollection? I want to take the advantage that in some cases I have the extra type information available, which lets me to do SomethigReallyCoolWithMyReallyCoolIterator :)

Sorry for the lack of a better example ;)
BaseCollection coll = new CoolCollection( ... );Iterator i1 = coll.Iterator;// ... if you don't know it's a CoolCollection, do stuff// with an ordinary iteratorCoolIterator i2 = ((CoolCollection)coll).Iterator;// now you can do cool stuff// alternatively ...CoolIterator i3 = (CoolIterator)coll.Iterator;


Does that not do what you need? After all, if you know the thing is Cool you should know you can cast it.

Or is the problem that your code won't compile? ... you can't override a property with one of a different type, because if you later add a setter your subclass is more restrictive in what you can set than the superclass. You can just cast the result (as in i3) if you know the thing is Cool, though.
Yep, you are absolutely right, and thank you for really trying to help.

Though, for the real problem it is too cumbersome to cast everytime since the class in fact looks more like this:

interface IPosition<PositionT, AccessorT, T> {}interface IReadablePosition<PositionT, AccessorT, T>  : IPosition<PositionT, AccessorT, T>{}interface IWriteablePosition<PositionT, AccessorT, T>{}//Here is how the above is used:interface IReadableCollectionAcc<T> {}interface IReadableCollectionPos<T>  : IReadablePosition< IReadableCollectionPos<T>, IReadableCollectionAcc<T>, T>{}interface IReadableCollection<T>{  IReadableCollectionPos<T> Begin { get; }  IReadableCollectionPos<T> End { get; }}static class MyAlgorithm{  public static void doCoolAlgorithm1<PositionT, AccessorT, T>(IPosition<PositionT, AccessorT, T> startPosition)    where PositionT: IReadablePosition<PositionT, AccessorT, T>  {    //Now you know that the position in fact is a readable    //you could add other requirements, lets say it has to    //be writeable as well:    //where PositionT: IWriteablePosition<PositionT, AccessorT, T>  }}


Phu! I know you could say that is code bloat and misuse of generics :P
I admit it is cumbersome for the library writer, but the user will never have to bother with the types anyway. For example:

IMyCollection<int> c = ...MyAlgorithm.doCoolAlgorithm1(c.Begin);MyOtherAlgorithm.doCoolAlgorithm2(c.Begin);//the iterators are also heavy on generics... but no worries :)var iter = ForwardIterator.from(c.Begin);//Just to show an example: BAD BAD ME :)iter.moveNext().moveNext().moveNext();//do some algorithm from c.Begin position to current iter.PositionMyThirdAlgorithm.doCoolAlgorithm3(c.Begin, iter.Position);


But you see now, that it would be too cumbersome to actually cast everytime I want to use a position :/

//This is not acceptableMyAlgorithm.doCoolAlgorithm1((IPosition<OH, MY, GOD>)c.Begin);


Anyway, I did solve the problems with the method I mentioned so everything works just ok. Thanks Bob Janova!

Bye!

This topic is closed to new replies.

Advertisement