PC Review


Reply
Thread Tools Rate Thread

Best way to call inherited method with var of base class?

 
 
=?Utf-8?B?UGhpbGlwIFdhcm5lcg==?=
Guest
Posts: n/a
 
      15th Nov 2004

I have a set of classes:

C (base)
C1 (inherits C)
C2 (inherits C)
...
Cn (inherits C)

(the C1..Cn also have subclasses, but thats not really relevant to the
question)

C has the following functions:

F(C) (implemented in C)
F(C1) (mustoverride)
...
F(Cn) (mustoverride)

When I declare two variables (x, y) of type C, and call x.F(y), it calls the
base class implementation of F(C) which is quite understandable. However, I
would like to actually call the appropriate F(Cn) based on the actual classes
of x & y.

What is the best way of doing this?

Currently I have a case statement inside F(C), which is (a) bad for
maintenance and (b) a kludge.


 
Reply With Quote
 
 
 
 
Herfried K. Wagner [MVP]
Guest
Posts: n/a
 
      15th Nov 2004
"Philip Warner" <(E-Mail Removed)> schrieb:
> I have a set of classes:
>
> C (base)
> C1 (inherits C)
> C2 (inherits C)
> ...
> Cn (inherits C)
>
> (the C1..Cn also have subclasses, but thats not really relevant to the
> question)
>
> C has the following functions:
>
> F(C) (implemented in C)
> F(C1) (mustoverride)
> ...
> F(Cn) (mustoverride)
>
> When I declare two variables (x, y) of type C, and call
> x.F(y), it calls the base class implementation of F(C) which
> is quite understandable. However, I would like to actually
> call the appropriate F(Cn) based on the actual classes
> of x & y.


http://groups.google.de/groups?selm=...TNGP11.phx.gbl

--
Herfried K. Wagner [MVP]
<URL:http://dotnet.mvps.org/>


 
Reply With Quote
 
=?Utf-8?B?UGhpbGlwIFdhcm5lcg==?=
Guest
Posts: n/a
 
      15th Nov 2004
"Herfried K. Wagner [MVP]" wrote:

>
> http://groups.google.de/groups?selm=...TNGP11.phx.gbl
>


I think you *may* have missed the point; I am not trying to call the base
class methods directly, I asm trying to ensure that the narrowest possible
function signature is used.

I can understand why VB needs to obey the class of the variable
declarations, but the question is: if I *want* to call the narrower function
based on the class of the parameters, what is the best way to do it?

In my specific example, I only have one level of inheritance, and there is
no code in the base class.



 
Reply With Quote
 
Jay B. Harlow [MVP - Outlook]
Guest
Posts: n/a
 
      15th Nov 2004
Philip.
> When I declare two variables (x, y) of type C, and call x.F(y), it calls
> the
> base class implementation of F(C) which is quite understandable. However,
> I
> would like to actually call the appropriate F(Cn) based on the actual
> classes
> of x & y.

It sounds like you want a double dispatch. Try something like:

Public MustInherit Class C

Public MustOverride Sub F(ByVal aC As C)
Public MustOverride Sub F(ByVal aC1 As C1)
Public MustOverride Sub F(ByVal aC2 As C2)
Public MustOverride Sub F(ByVal aC3 As C3)

End Class

Public Class C1
Inherits C

Public Overloads Overrides Sub F(ByVal aC As C)
' Me is now C1, so C.F(C1) is called
aC.F(Me)
End Sub

Public Overloads Overrides Sub F(ByVal aC1 As C1)
Debug.WriteLine("F(c1)", "C1")
End Sub

Public Overloads Overrides Sub F(ByVal aC2 As C2)
Debug.WriteLine("F(c2)", "C1")
End Sub

Public Overloads Overrides Sub F(ByVal aC3 As C3)
Debug.WriteLine("F(c3)", "C1")
End Sub

End Class

Public Class C2
Inherits C

Public Overloads Overrides Sub F(ByVal aC As C)
' Me is now C2, so C.F(C2) is called
aC.F(Me)
End Sub

Public Overloads Overrides Sub F(ByVal aC1 As C1)
Debug.WriteLine("F(c1)", "C2")
End Sub

Public Overloads Overrides Sub F(ByVal aC2 As C2)
Debug.WriteLine("F(c2)", "C2")
End Sub

Public Overloads Overrides Sub F(ByVal aC3 As C3)
Debug.WriteLine("F(c3)", "C2")
End Sub

End Class

Public Class C3
Inherits C

Public Overloads Overrides Sub F(ByVal aC As C)
' Me is now C3, so C.F(C3) is called
aC.F(Me)
End Sub

Public Overloads Overrides Sub F(ByVal aC1 As C1)
Debug.WriteLine("F(c1)", "C3")
End Sub

Public Overloads Overrides Sub F(ByVal aC2 As C2)
Debug.WriteLine("F(c2)", "C3")
End Sub

Public Overloads Overrides Sub F(ByVal aC3 As C3)
Debug.WriteLine("F(c3)", "C3")
End Sub

End Class


FWIW: Rather then overloading function F, I normally give each a distinct
name, something like:

Public MustInherit Class C

Public MustOverride Sub F(ByVal aC As C)
Public MustOverride Sub FC1(ByVal aC1 As C1)
Public MustOverride Sub FC2(ByVal aC2 As C2)
Public MustOverride Sub FC3(ByVal aC3 As C3)

End Class

If don't want the "reversal" of the parameters you can make F a template
method. Something like:

Public MustInherit Class C

Public Sub F(ByVal aC As C)
aC.FC(Me)
End Sub

Public MustOverride Sub FC(ByVal aC As C)
Public MustOverride Sub FC1(ByVal aC1 As C1)
Public MustOverride Sub FC2(ByVal aC2 As C2)
Public MustOverride Sub FC3(ByVal aC3 As C3)

End Class

Hope this helps
Jay



"Philip Warner" <(E-Mail Removed)> wrote in message
news:CC3A6F15-8990-41B0-9B9D-(E-Mail Removed)...
>
> I have a set of classes:
>
> C (base)
> C1 (inherits C)
> C2 (inherits C)
> ...
> Cn (inherits C)
>
> (the C1..Cn also have subclasses, but thats not really relevant to the
> question)
>
> C has the following functions:
>
> F(C) (implemented in C)
> F(C1) (mustoverride)
> ...
> F(Cn) (mustoverride)
>
> When I declare two variables (x, y) of type C, and call x.F(y), it calls
> the
> base class implementation of F(C) which is quite understandable. However,
> I
> would like to actually call the appropriate F(Cn) based on the actual
> classes
> of x & y.
>
> What is the best way of doing this?
>
> Currently I have a case statement inside F(C), which is (a) bad for
> maintenance and (b) a kludge.
>
>



 
Reply With Quote
 
=?Utf-8?B?UGhpbGlwIFdhcm5lcg==?=
Guest
Posts: n/a
 
      16th Nov 2004
> It sounds like you want a double dispatch.

Thanks for this; it's very long-winded but it will achieve the result.

I don't suppose you know of any way I can do it using Reflection and the
Type object etc? It would be nice to avoid writing two functions for every
one I need.

 
Reply With Quote
 
Jay B. Harlow [MVP - Outlook]
Guest
Posts: n/a
 
      16th Nov 2004
Philip,
I'm sure you could kludge together something with Reflection. However I have
to ask why?

Using Reflection I'm certain would be more fragile, and perform
significantly worse (as late binding or Reflection pretty much always
perform worse), and possibly be harder to follow. Granted double dispatch is
a little more advance then normal overridable functions, however not that
much more as you are simply having an overridable function call an
overridable function.

Also I don't think Reflection you are really going to save on the number of
functions you need (see below).

Try single stepping the following version to see how the double dispatch
works.

---x--- cut here ---x---
Public MustInherit Class C

Public Sub F(ByVal aC As C)
aC.Fc(Me)
End Sub

Public MustOverride Sub Fc(ByVal aC As C)

' NOTE we use qualified names rather then overloading here
' we could have just as easily call these all Fc...
Public MustOverride Sub Fc1(ByVal aC1 As C1)
Public MustOverride Sub Fc2(ByVal aC2 As C2)
Public MustOverride Sub Fc3(ByVal aC3 As C3)
Public MustOverride Sub Fc4(ByVal aC4 As C4)

End Class

Public Class C1
Inherits C

Public Overrides Sub Fc(ByVal aC As C)
aC.Fc1(Me)
End Sub

Public Overrides Sub Fc1(ByVal aC1 As C1)
Debug.WriteLine("Fc1(c1)", "c1")
End Sub

Public Overrides Sub Fc2(ByVal aC2 As C2)
Debug.WriteLine("Fc2(c2)", "c1")
End Sub

Public Overrides Sub Fc3(ByVal aC3 As C3)
Debug.WriteLine("Fc3(c3)", "c1")
End Sub

Public Overrides Sub Fc4(ByVal aC4 As C4)
Debug.WriteLine("Fc4(c4)", "c1")
End Sub

End Class

Public Class C2
Inherits C

Public Overrides Sub Fc(ByVal aC As C)
aC.Fc2(Me)
End Sub

Public Overrides Sub Fc1(ByVal aC1 As C1)
Debug.WriteLine("Fc1(c1)", "c2")
End Sub

Public Overrides Sub Fc2(ByVal aC2 As C2)
Debug.WriteLine("Fc2(c2)", "c2")
End Sub

Public Overrides Sub Fc3(ByVal aC3 As C3)
Debug.WriteLine("Fc3(c3)", "c2")
End Sub

Public Overrides Sub Fc4(ByVal aC4 As C4)
Debug.WriteLine("Fc4(c4)", "c2")
End Sub

End Class

Public Class C3
Inherits C

Public Overrides Sub Fc(ByVal aC As C)
aC.Fc3(Me)
End Sub

Public Overrides Sub Fc1(ByVal aC1 As C1)
Debug.WriteLine("Fc1(c1)", "c3")
End Sub

Public Overrides Sub Fc2(ByVal aC2 As C2)
Debug.WriteLine("Fc2(c2)", "c3")
End Sub

Public Overrides Sub Fc3(ByVal aC3 As C3)
Debug.WriteLine("Fc3(c3)", "c3")
End Sub

Public Overrides Sub Fc4(ByVal aC4 As C4)
Debug.WriteLine("Fc4(c4)", "c3")
End Sub

End Class

Public Class C4
Inherits C

Public Overrides Sub Fc(ByVal aC As C)
aC.Fc4(Me)
End Sub

Public Overrides Sub Fc1(ByVal aC1 As C1)
Debug.WriteLine("Fc1(c1)", "c4")
End Sub

Public Overrides Sub Fc2(ByVal aC2 As C2)
Debug.WriteLine("Fc2(c2)", "c4")
End Sub

Public Overrides Sub Fc3(ByVal aC3 As C3)
Debug.WriteLine("Fc3(c3)", "c4")
End Sub

Public Overrides Sub Fc4(ByVal aC4 As C4)
Debug.WriteLine("Fc4(c4)", "c4")
End Sub

End Class

Public Class Test

Public Shared Sub Main()
Dim xlist() As C = {New C1, New C2, New C3, New C4}
Dim ylist() As C = {New C1, New C2, New C3, New C4}

For Each x As C In xlist
For Each y As C In ylist
Debug.WriteLine(x, "x")
Debug.WriteLine(y, "y")
x.F(y)
Debug.WriteLine(Nothing)
Next
Next
End Sub

End Class

---x--- cut here ---x---

If you are really not following the double dispatch I would recommend you
use a select case as you originally suggested and avoid reflection. As the
select case will be easier to understand and perform better then using
Reflection.

However! I recommend Double Dispatch as it is a rather common OO method to
solve the problem you seem to be stating. For example: The Visitor Pattern
is commonly implemented as Double Dispatch in single inheritance languages
such as VB.NET & C#.

> I don't suppose you know of any way I can do it using Reflection and the
> Type object etc? It would be nice to avoid writing two functions for every
> one I need.

Why do you think there are twice as many as you need?

You need (N+1)^2 functions, you write (N+1)^2 functions. Your original post
suggested class C1 to CN need functions F(C1) to F(CN), the double dispatch
code has F(C1) to F(CN) + F(C) in each class, which for an number of N > 1
does not add up to "twice as many"...

In other words with Double Dispatch, if you have N classes you need N
functions per class, plus you need 1 extra function per class that actually
does the double dispatch.

Your original post suggested if you have N classes you would have N
functions per class (as all the functions were MustOverride). Double
dispatch is simply adding +1 to each class.

In both cases you have an abstact base class, simply to define what the
above classes need to look like. Of course if some combinations of F(C1) to
F(CN) are not logical you could always leave them in the base class as
simply Overridable & provide "default" implementation for all the derived
classes...

Unfortunately I am not seeing any really good links on double dispatch.

Hope this helps
Jay

"Philip Warner" <(E-Mail Removed)> wrote in message
news:5F0EEC90-07FB-44D0-937A-(E-Mail Removed)...
>> It sounds like you want a double dispatch.

>
> Thanks for this; it's very long-winded but it will achieve the result.
>
> I don't suppose you know of any way I can do it using Reflection and the
> Type object etc? It would be nice to avoid writing two functions for every
> one I need.
>



 
Reply With Quote
 
=?Utf-8?B?UGhpbGlwIFdhcm5lcg==?=
Guest
Posts: n/a
 
      16th Nov 2004
> I'm sure you could kludge together something with Reflection. However I have
> to ask why?


Ignorance?


> Using Reflection I'm certain would be more fragile, and perform
> significantly worse


Then I'll avoid it.


> However! I recommend Double Dispatch as it is a rather common OO method to
> solve the problem you seem to be stating.


It what I have currently (badly) implemented (after I gave up on the case
statement); I made the mistake of thinking I needed to implement n Fc's,
rather than 1 Fc and n Fc1's...if that makes sense. Much happier now.


> Why do you think there are twice as many as you need?


In this case, fuzzy thinking...it was late at night...the dog ate my homework.


> Unfortunately I am not seeing any really good links on double dispatch.


No problem; I'll use double-dispatching, especially now that I have an
official-sounding name for it.

Thanks for you extremely helpful replies.


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can a base class method return an object of an inherited class typ Ethan Strauss Microsoft C# .NET 12 12th Jan 2008 12:41 AM
how to make sure this.Test() call base class method in base class constructor Ryan Liu Microsoft C# .NET 2 27th Aug 2006 07:43 PM
How to call an ancestor base class method ? cadilhac@gmail.com Microsoft C# .NET 2 7th Jan 2005 07:25 PM
How to use the base keyword to call a base class method (not a constructor) Bob Rock Microsoft C# .NET 1 26th Aug 2003 01:27 PM
How to call a base class's base class method Bill Menees Microsoft C# .NET 1 23rd Jul 2003 02:17 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:25 AM.