Sign in to follow this  

[.net] inheritance ?

This topic is 4102 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 :(

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ;)

Share this post


Link to post
Share on other sites
BaseCollection coll = new CoolCollection( ... );

Iterator i1 = coll.Iterator;
// ... if you don't know it's a CoolCollection, do stuff
// with an ordinary iterator
CoolIterator 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.

Share this post


Link to post
Share on other sites
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.Position
MyThirdAlgorithm.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 acceptable
MyAlgorithm.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!

Share this post


Link to post
Share on other sites

This topic is 4102 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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