Base class referring to inheritor

  • Thread starter Ertugrul Söylemez
  • Start date
E

Ertugrul Söylemez

Hello people,

I would like to write a base class in the following way:

abstract class Something<T> {
// ...
public abstract void unpack(Something<Something<T>>);
// ...
}

An inheriting class should define the 'unpack' method such that
instances of Something<T> can become whatever is in a
Something<Something<T>> in some way that makes sense.

Example: Where 'xs' is a list of type MyList<T> and and 'xss' is a list
of lists of type MyList<MyList<T>>, 'xs.unpack(xss)' replaces the list
contained by 'xs' with the concatenation of all lists contained by 'xss'
such that:

xs = someList
xss = {{10,11,12}, {14,17}, {19,20,22}}

// After xs.unpack(xss):
xs = {10,11,12,14,17,19,20,22}
xss = {{10,11,12}, {14,17}, {19,20,22}}

The problem is this: The MyList<T>.unpack method can be called with any
Something<Something<T>>, so I have to use explicit casting, which is
very ugly and not type-safe:

class MyList<T> : Something<T> {
// ...
public override void unpack(Something<Something<T>> cc) {
MyList<MyList<T>> xss = cc as MyList<MyList<T>>;

// ...
}
// ...
}

Is there an elegant way to solve this? There doesn't seem to be a way
to refer to more special classes from a base class.

Interfaces don't solve this either, because I can't refer to the
particular type implemented by the interface.

Any ideas?


Greets,
Ertugrul.
 
P

Paul

I suggest you first look at the thread started by Ivan 'How do I know type
of implementing object'.

Then I suggest you come explain below a little better. i got lost when
MyList started implemeting MySomething.

I particularly loved this line
An inheriting class should define the 'unpack' method such that
instances of Something<T> can become whatever is in a
Something<Something<T>> in some way that makes sense.

Sense not likely.......LOL...Tongue twister maybe...
Interfaces don't solve this either, because I can't refer to the
particular type implemented by the interface.

This is not entirely true. Create a asbtract method in the base class and
calling this method from the base type will call the method in the
implementing type. God ive confused myself now.

Any chance of a real world examle and not List/Somethign<T>
 
P

Paul

I suggest you first look at the thread started by Ivan 'How do I know type
of implementing object'.

Then I suggest you come explain below a little better. i got lost when
MyList started implemeting MySomething.

I particularly loved this line
An inheriting class should define the 'unpack' method such that
instances of Something<T> can become whatever is in a
Something<Something<T>> in some way that makes sense.

Sense not likely.......LOL...Tongue twister maybe...
Interfaces don't solve this either, because I can't refer to the
particular type implemented by the interface.

This is not entirely true. Create a asbtract method in the base class and
calling this method from the base type will call the method in the
implementing type. God ive confused myself now.

Any chance of a real world examle and not List/Somethign<T>
 
E

Ertugrul Söylemez

Paul said:
I suggest you first look at the thread started by Ivan 'How do I know type
of implementing object'.

Then I suggest you come explain below a little better. i got lost when
MyList started implemeting MySomething.

I particularly loved this line


Sense not likely.......LOL...Tongue twister maybe...


This is not entirely true. Create a asbtract method in the base class and
calling this method from the base type will call the method in the
implementing type. God ive confused myself now.

It seems like you are confusing this with OOP polymorphism. What I need
is type polymorphism. C# and other .NET languages provide that to some
extent, but not to the extent I'd like them to. I could use 'template
templates' in C++ for that, but I'd like to stick with C#, as I don't
like C++ syntax.

Any chance of a real world examle and not List/Somethign<T>

A less abstract example: The notion of mapping a function over whatever
a type contains. The following interface implements this idea:

interface Mappable<A> {
Mappable<B> map<B>(Func<A, B> f);
}

As its name suggests, the 'map' function is supposed to map a function
over whatever is contained in the Mappable. Consider a container, which
contains exactly one value. That container is a Mappable:

class OneValue<A> : Mappable<A> {
public A value;

public OneValue(v) { value = v; }

public Mappable<B> map<B>(Func<A, B> f) {
return new OneValue(f(value));
}
}

You could implement the 'map' function for any type, which can be
interpreted as a container.

However, here I'm facing the same problem: In the OneValue class, 'map'
does not return a OneValue, but a Mappable, so that I need type-casting
outside of the 'map' function. I'd like to get rid of this
type-casting, if that's possible, because it's messy and error-prone
(not only in this particular case, but casting is a bad idea in general).


Greets,
Ertugrul.
 
E

Ertugrul Söylemez

Paul said:
I suggest you first look at the thread started by Ivan 'How do I know type
of implementing object'.

Then I suggest you come explain below a little better. i got lost when
MyList started implemeting MySomething.

I particularly loved this line


Sense not likely.......LOL...Tongue twister maybe...


This is not entirely true. Create a asbtract method in the base class and
calling this method from the base type will call the method in the
implementing type. God ive confused myself now.

It seems like you are confusing this with OOP polymorphism. What I need
is type polymorphism. C# and other .NET languages provide that to some
extent, but not to the extent I'd like them to. I could use 'template
templates' in C++ for that, but I'd like to stick with C#, as I don't
like C++ syntax.

Any chance of a real world examle and not List/Somethign<T>

A less abstract example: The notion of mapping a function over whatever
a type contains. The following interface implements this idea:

interface Mappable<A> {
Mappable<B> map<B>(Func<A, B> f);
}

As its name suggests, the 'map' function is supposed to map a function
over whatever is contained in the Mappable. Consider a container, which
contains exactly one value. That container is a Mappable:

class OneValue<A> : Mappable<A> {
public A value;

public OneValue(v) { value = v; }

public Mappable<B> map<B>(Func<A, B> f) {
return new OneValue(f(value));
}
}

You could implement the 'map' function for any type, which can be
interpreted as a container.

However, here I'm facing the same problem: In the OneValue class, 'map'
does not return a OneValue, but a Mappable, so that I need type-casting
outside of the 'map' function. I'd like to get rid of this
type-casting, if that's possible, because it's messy and error-prone
(not only in this particular case, but casting is a bad idea in general).


Greets,
Ertugrul.
 
P

Pavel Minaev

I would like to write a base class in the following way:

  abstract class Something<T> {
    // ...
    public abstract void unpack(Something<Something<T>>);
    // ...
  }

An inheriting class should define the 'unpack' method such that
instances of Something<T> can become whatever is in a
Something<Something<T>> in some way that makes sense.

Example:  Where 'xs' is a list of type MyList<T> and and 'xss' is a list
of lists of type MyList<MyList<T>>, 'xs.unpack(xss)' replaces the list
contained by 'xs' with the concatenation of all lists contained by 'xss'
such that:

  xs = someList
  xss = {{10,11,12}, {14,17}, {19,20,22}}

  // After xs.unpack(xss):
  xs = {10,11,12,14,17,19,20,22}
  xss = {{10,11,12}, {14,17}, {19,20,22}}

The problem is this:  The MyList<T>.unpack method can be called with any
Something<Something<T>>, so I have to use explicit casting, which is
very ugly and not type-safe:

  class MyList<T> : Something<T> {
    // ...
    public override void unpack(Something<Something<T>> cc) {
      MyList<MyList<T>> xss = cc as MyList<MyList<T>>;

      // ...
    }
    // ...
  }

Is there an elegant way to solve this?  There doesn't seem to be a way
to refer to more special classes from a base class.

The usual way to do this is to have the derived class pass itself as a
template parameter to a base class, i.e.:

class Base<TDerived> where TDerived : Base<TDerived> { }
class Derived : Base<Derived> { }

In your case however you want more than that, because you do not want
access to a specific derived class for a particular instantiation -
you want access to the whole generic family of derived types (simply
put, you want "MyList<>", and not "MyList<T>" for a specific T). For
the earlier trick to work in this case, you'd need something like
template template parameters of C++, but there is no such thing in C#.
And I don't know of any other ways to do the same.

It should be noted, however, that the very design is suspect, since it
violates Liskov substitution principle. Looking at the API for
Something<T>, it would seem that I can call unpack with any
Something<Something<T>>, but in practice you restrict the types
further in derived classes. So your derived classes have stronger
precondition than their base class - which violates LSP, and hints at
wrong design.
 
P

Pavel Minaev

I would like to write a base class in the following way:

  abstract class Something<T> {
    // ...
    public abstract void unpack(Something<Something<T>>);
    // ...
  }

An inheriting class should define the 'unpack' method such that
instances of Something<T> can become whatever is in a
Something<Something<T>> in some way that makes sense.

Example:  Where 'xs' is a list of type MyList<T> and and 'xss' is a list
of lists of type MyList<MyList<T>>, 'xs.unpack(xss)' replaces the list
contained by 'xs' with the concatenation of all lists contained by 'xss'
such that:

  xs = someList
  xss = {{10,11,12}, {14,17}, {19,20,22}}

  // After xs.unpack(xss):
  xs = {10,11,12,14,17,19,20,22}
  xss = {{10,11,12}, {14,17}, {19,20,22}}

The problem is this:  The MyList<T>.unpack method can be called with any
Something<Something<T>>, so I have to use explicit casting, which is
very ugly and not type-safe:

  class MyList<T> : Something<T> {
    // ...
    public override void unpack(Something<Something<T>> cc) {
      MyList<MyList<T>> xss = cc as MyList<MyList<T>>;

      // ...
    }
    // ...
  }

Is there an elegant way to solve this?  There doesn't seem to be a way
to refer to more special classes from a base class.

The usual way to do this is to have the derived class pass itself as a
template parameter to a base class, i.e.:

class Base<TDerived> where TDerived : Base<TDerived> { }
class Derived : Base<Derived> { }

In your case however you want more than that, because you do not want
access to a specific derived class for a particular instantiation -
you want access to the whole generic family of derived types (simply
put, you want "MyList<>", and not "MyList<T>" for a specific T). For
the earlier trick to work in this case, you'd need something like
template template parameters of C++, but there is no such thing in C#.
And I don't know of any other ways to do the same.

It should be noted, however, that the very design is suspect, since it
violates Liskov substitution principle. Looking at the API for
Something<T>, it would seem that I can call unpack with any
Something<Something<T>>, but in practice you restrict the types
further in derived classes. So your derived classes have stronger
precondition than their base class - which violates LSP, and hints at
wrong design.
 
E

Ertugrul Söylemez

Pavel said:
The usual way to do this is to have the derived class pass itself as a
template parameter to a base class, i.e.:

class Base<TDerived> where TDerived : Base<TDerived> { }
class Derived : Base<Derived> { }

In your case however you want more than that, because you do not want
access to a specific derived class for a particular instantiation -
you want access to the whole generic family of derived types (simply
put, you want "MyList<>", and not "MyList<T>" for a specific T). For
the earlier trick to work in this case, you'd need something like
template template parameters of C++, but there is no such thing in C#.
And I don't know of any other ways to do the same.

Yes, I suspected that.

It should be noted, however, that the very design is suspect, since it
violates Liskov substitution principle. Looking at the API for
Something<T>, it would seem that I can call unpack with any
Something<Something<T>>, but in practice you restrict the types
further in derived classes. So your derived classes have stronger
precondition than their base class - which violates LSP, and hints at
wrong design.

I know it is unusual C# code. I like generalization of functionality to
the point where I can write not only abstract interfaces, but also
abstract algorithms, i.e. algorithms for Something<> or even something
more general, which implement a general idea, but behave differently
depending on the actual type/class. Unfortunately C# and other .NET
languages (with the exception of F#, as far as I have seen) don't
support this very well.

Regarding the Liskov substitution principle, the Something<> class is
abstract. It implements abstract methods as well as generalized
algorithms. Think of it as an 'idea'. You cannot instantiate it.


Greets,
Ertugrul.
 
E

Ertugrul Söylemez

Pavel said:
The usual way to do this is to have the derived class pass itself as a
template parameter to a base class, i.e.:

class Base<TDerived> where TDerived : Base<TDerived> { }
class Derived : Base<Derived> { }

In your case however you want more than that, because you do not want
access to a specific derived class for a particular instantiation -
you want access to the whole generic family of derived types (simply
put, you want "MyList<>", and not "MyList<T>" for a specific T). For
the earlier trick to work in this case, you'd need something like
template template parameters of C++, but there is no such thing in C#.
And I don't know of any other ways to do the same.

Yes, I suspected that.

It should be noted, however, that the very design is suspect, since it
violates Liskov substitution principle. Looking at the API for
Something<T>, it would seem that I can call unpack with any
Something<Something<T>>, but in practice you restrict the types
further in derived classes. So your derived classes have stronger
precondition than their base class - which violates LSP, and hints at
wrong design.

I know it is unusual C# code. I like generalization of functionality to
the point where I can write not only abstract interfaces, but also
abstract algorithms, i.e. algorithms for Something<> or even something
more general, which implement a general idea, but behave differently
depending on the actual type/class. Unfortunately C# and other .NET
languages (with the exception of F#, as far as I have seen) don't
support this very well.

Regarding the Liskov substitution principle, the Something<> class is
abstract. It implements abstract methods as well as generalized
algorithms. Think of it as an 'idea'. You cannot instantiate it.


Greets,
Ertugrul.
 
P

Paul

You may wish to look at the Visitor pattern.

I was trying to understand what you were trying to achieve from the outset
more than anything.
 
P

Paul

You may wish to look at the Visitor pattern.

I was trying to understand what you were trying to achieve from the outset
more than anything.
 
P

Pavel Minaev

I know it is unusual C# code.  I like generalization of functionality to
the point where I can write not only abstract interfaces, but also
abstract algorithms, i.e. algorithms for Something<> or even something
more general, which implement a general idea, but behave differently
depending on the actual type/class.  Unfortunately C# and other .NET
languages (with the exception of F#, as far as I have seen) don't
support this very well.

Since F# has the same limitations as C# when it comes to generics
(which is really CLR limitations for the most part), I don't see how
F# would help you there. Can you give an example?
Regarding the Liskov substitution principle, the Something<> class is
abstract.  It implements abstract methods as well as generalized
algorithms.  Think of it as an 'idea'.  You cannot instantiate it.

It doesn't matter for LSP purposes. I can still write a method that
takes a reference to Something<> as an argument. When LSP is upheld,
such method is actually usable because it can use the entire interface
of Something<>, and expect it to behave in a certain way, regardless
of the particular subclass that is there.
 
P

Pavel Minaev

I know it is unusual C# code.  I like generalization of functionality to
the point where I can write not only abstract interfaces, but also
abstract algorithms, i.e. algorithms for Something<> or even something
more general, which implement a general idea, but behave differently
depending on the actual type/class.  Unfortunately C# and other .NET
languages (with the exception of F#, as far as I have seen) don't
support this very well.

Since F# has the same limitations as C# when it comes to generics
(which is really CLR limitations for the most part), I don't see how
F# would help you there. Can you give an example?
Regarding the Liskov substitution principle, the Something<> class is
abstract.  It implements abstract methods as well as generalized
algorithms.  Think of it as an 'idea'.  You cannot instantiate it.

It doesn't matter for LSP purposes. I can still write a method that
takes a reference to Something<> as an argument. When LSP is upheld,
such method is actually usable because it can use the entire interface
of Something<>, and expect it to behave in a certain way, regardless
of the particular subclass that is there.
 
E

Ertugrul Söylemez

Pavel Minaev said:
Since F# has the same limitations as C# when it comes to generics
(which is really CLR limitations for the most part), I don't see how
F# would help you there. Can you give an example?

I may be wrong. I can say more, when I've used it myself.

It doesn't matter for LSP purposes. I can still write a method that
takes a reference to Something<> as an argument. When LSP is upheld,
such method is actually usable because it can use the entire interface
of Something<>, and expect it to behave in a certain way, regardless
of the particular subclass that is there.

Yes, that's the point of this design. That problem would be a
non-issue, if what I was asking for in the original post were possible
in C#. It isn't, so I live with that and currently I also live with the
ugly casting. There doesn't seem to be a way around it.


Greets,
Ertugrul.
 
E

Ertugrul Söylemez

Pavel Minaev said:
Since F# has the same limitations as C# when it comes to generics
(which is really CLR limitations for the most part), I don't see how
F# would help you there. Can you give an example?

I may be wrong. I can say more, when I've used it myself.

It doesn't matter for LSP purposes. I can still write a method that
takes a reference to Something<> as an argument. When LSP is upheld,
such method is actually usable because it can use the entire interface
of Something<>, and expect it to behave in a certain way, regardless
of the particular subclass that is there.

Yes, that's the point of this design. That problem would be a
non-issue, if what I was asking for in the original post were possible
in C#. It isn't, so I live with that and currently I also live with the
ugly casting. There doesn't seem to be a way around it.


Greets,
Ertugrul.
 

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