Inheritance and Shared Methods

J

Joe Fallon

1. I have a Base class that has a certain amount of functionality.
2. Then I have a CodeSmith generated class that inherits from the Base class
and adds functionality.
3. Since I want to be able to re-generate the classes on level 2 I have a
3rd level that inherits from them and implements specific hand coded
methods.
4. My colleague asked me to create a 4th level class that inherits the 3rd
level class so he can write custom functionality that overrides the "plain"
functionality at all levels above it.

I have 1-3 implemented as Shared methods.
To me, this enables simpler UI code.

For example:
strSQL = Level3ClassName.Select

In this way I do not need to instantiate an instance of the class I just use
the shared methods in levels 1-3.

===========================================================
My problem (other than being new and not really understanding this well
enough yet <g> )
is I don't know how to implement Level 4 in a way that allows me to use
Shared methods in levels1-3 and yet Override them in Level 4.

Is it not possible?
==============================================================

If I have to change Levels 1-3 what would you recommend?

================================================

Sample code:

Level 1
Public MustInherit Class Base

Public Shared Function DoSomething(ByVal Source As String) As String

End Function


================================================
Level 2
Public MustInherit Class GeneratedStuff

Inherits Base

Public Shared Function DoSomethingElse(ByVal Source As String) As String

End Function


================================================
Level 3
Public MustInherit Class HandCodedStuff

Inherits GeneratedStuff

Public Shared Function IWroteThis(ByVal Source As String) As String

End Function


================================================
Level 4 (implements same functionality as Level 3 but also allows customized
changes by overriding methods or creating new ones that are specific to a
single client. Level 3 functionality is for all clients.)
Public MustInherit Class FinalLevel

Inherits HandCodedStuff

Overrides Function DoSomethingElse(ByVal Source As String) As String

End Function



Thanks for any advice!
 
S

Scott M.

I would think that in the 4th class if you wanted to use the shared methods
from classes 1-3, you would say "myBase.method" and in the 4th class you
could define an Overrides method that overrides the shared method in the
base class.
 
F

Fergus Cooney

Hi Joe,

If you want to keep your methods as Shared then you can't use Overrides in
Level 4. Overrideable and Overrides are only available with object methods, so
that would be goodbye to your Shared..

There is, however, the option of using Shadows. In FinalLevel,
Shadows Function DoSomethingElse(...) As String
will make the name DoSomethingElse available to users of that class.

If you were doing this using object methods and Overrides, you would call
the base class method using MyBase.SameMethod as Scott pointed out.

With Shared methods the equivalent is simply to use the name of the base
class.

So you could have:
'Level 2
Public MustInherit Class GeneratedStuff
Inherits Base
Public Shared Function DoSomethingElse(...) As String
End Function
End Class

'Level 4
Public MustInherit Class FinalLevel_Client1
Inherits HandCodedStuff
Shadows Public Shared Function DoSomethingElse(...) As String
GeneratedStuff.DoSomethingElse(...) 'If necessary:
'Do Client1's something else.
End Function
End Class

'Ditto for Client2, etc.

Regards,
Fergus
 
H

Herfried K. Wagner [MVP]

* "Joe Fallon said:
1. I have a Base class that has a certain amount of functionality.
2. Then I have a CodeSmith generated class that inherits from the Base class
and adds functionality.
3. Since I want to be able to re-generate the classes on level 2 I have a
3rd level that inherits from them and implements specific hand coded
methods.
4. My colleague asked me to create a 4th level class that inherits the 3rd
level class so he can write custom functionality that overrides the "plain"
functionality at all levels above it.

I have 1-3 implemented as Shared methods.
To me, this enables simpler UI code.

You cannot override a shared method. I would suggest to remove the
'Shared' from the declaration and implement something like the Singleton
design pattern. You can make a Google search if you want to get more
information on the Singleton pattern.
 
J

Jay B. Harlow [MVP - Outlook]

Scott,
Overrides & Shared are incompatible. You can only override Overridable
methods. Overridable methods cannot be Shared.

Hope this helps
Jay
 
S

Scott M.

What about Shadows then?


Jay B. Harlow said:
Scott,
Overrides & Shared are incompatible. You can only override Overridable
methods. Overridable methods cannot be Shared.

Hope this helps
Jay

have to
 
J

Jay B. Harlow [MVP - Outlook]

Joe,
I would recommend a Singleton pattern as Herfried suggested. The "problem"
your going to have is where to put the singleton. Ideally you would make
Base the Singleton, however that makes it difficult for the derived classes
to override implementation. You could make the derived classes the
singleton, however then your program is 'hard coded' to the derived class.

The approach I would consider is to make Base the Singleton, however I would
store the class name to use in the app.config file. When the base creates
the instance of the singleton, it would get the class out of the app.config.
Effectively combining the Singleton Pattern with a PlugIn pattern.

http://www.yoda.arachsys.com/csharp/singleton.html
http://www.martinfowler.com/eaaCatalog/plugin.html

Something like:

Imports System.Configuration

Public MustInherit Class Base

#Region " Singleton support "

Private Shared m_instance As Base

Public Shared Readonly Property Instance() As Base
Get
If m_instance is Nothing Then
Dim s As String =
ConfigurationSettings.AppSettings("base.type")
Dim t As Type = Type.GetType(s)
m_instance =
DirectCast(Activator.CreateInstance(t,True), Base)
End If
Return m_Instance
End Get
End Property

Protected Sub New()
End Sub

#End Region

Public Function DoSomething(ByVal Source As String) As String
End Function

Public MustOverride Function DoSomethingElse(ByVal Source As String)
As String

Public MustOverride Function IWroteThis(ByVal Source As String) As
String

End Class

Public MustInherit Class GeneratedStuff
Inherits Base


Protected Sub New()
End Sub

Public Overrides Function DoSomethingElse(ByVal Source As String) As
String
End Function

End Class

Public Class HandCodedStuff
Inherits GeneratedStuff


Protected Sub New()
End Sub

Public Overrides Function IWroteThis(ByVal Source As String) As
String
End Function

End Class

Public Class FinalLevel
Inherits HandCodedStuff


Protected Sub New()
End Sub

Public Overrides Function DoSomethingElse(ByVal Source As String) As
String
End Function

End Class

' The app.config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="base.type" value="myproject.FinalLevel, myproject" />
</appSettings>
</configuration>

Then when you need to use the instance you simply use:

Dim source As String
Base.Instance.DoSomething(source)
Base.Instance.IWroteThis(source)
Base.Instance.DoSomethingElse(source)

Note the type in the config file should be in the format
"mynamespace.myclass, myassembly", where myclass is the class name you are
using, mynamespace is the namespace that class belongs to, and myassembly is
the assembly where the class is. Normally you can get the namespace &
assembly from the Project Properties. In the above case myclass can be
either FinalLevel or HandCodedStuff.

Note: The True in "Activator.CreateInstance(t,True)", allows non public
constructors to be used, this allows you to add the protected constructors
preventing the class from being created outside of the singleton pattern.

If the above is included in a class library assembly, I would define a
custom section for app.config file. Each app that used the class library
would then need to include the custom section in their app.config. This
allows better isolation for the class library settings verses the
application settings.

Public Shared ReadOnly Property Instance() As Base
Get
If m_instance Is Nothing Then
Dim col As IDictionary =
DirectCast(ConfigurationSettings.GetConfig("myprojectSettings"),
IDictionary)
Dim s As String = DirectCast(col("type"), String)
Dim t As Type = Type.GetType(s)
m_instance = DirectCast(Activator.CreateInstance(t, True),
Base)
End If
Return m_instance
End Get
End Property

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="myprojectSettings"
type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<appSettings>
</appSettings>
<myprojectSettings type="FunWithButtons.FinalLevel,
Fun.With.Buttons" />
</configuration>

The thing I like about the custom configuration section is you can give more
meaningful names, such as the assembly name & "type" for the value.

Hope this helps
Jay
 
F

Fergus Cooney

Hi Scott,

If you are ignoring my posts, you won't have seen that I recommended using
Shadows in this case.

Regards,
Fergus
 
J

Jay B. Harlow [MVP - Outlook]

Scott,
As Fergus stated, he wrote up a little something on Shadows.

The problem is that Shadows does not Override functionality. Shadows Hides
functionality.

If you used Shadows and referred to the base class you will get the base
class functionality. The way I read Joe's comments, he wants to override the
base class functionality, in that he could refer to the base class and see
the replaced functionality.

Don't get me wrong you can use Shadows in a situation like this, and in some
ways its the "easiest" thing to use in Joe's case. However just be certain
you know what Shadows is giving you & not giving you.

For a sample of how to use Overrides in Joe's case, see my other long post
to this thread.

Hope this helps
Jay
 
H

Herfried K. Wagner [MVP]

* "Fergus Cooney said:
If you are ignoring my posts, you won't have seen that I recommended using
Shadows in this case.

Your post is an advice to use 'Shadows' which doesn't make sense.
Please be so kind to say thanks if someone tells you that you made a
mistake.
 
F

Fergus Cooney

Good morning Herfried,

Joe gives reasons for wanting to use Shared methods. You may have chosen
to ignore them. The Singleton pattern, while suitable for situations like
this, means that Joe wouldn't continue to enjoy the benefits of avoidiug
object instances and the like.

Using Shadows is a single-word solution. It allows Joe to do exactly what
he asked.

Using the Singleton Pattern takes him into a different ball park. It would
have its own benefits, of course, but learning and implementing it means a
short diversion for Joe.

I hope that Joe learns the Singleton Pattern and continues to learn many
more Design Patterns. But whether he chooses to do so now or uses Shadows now
and learns more OOP later is his choice.

If you fail to see sense in my solution, I suggest that you study a bit
more.

Regards,
Fergus

ps. I was not aware that I had been corrected by anybody. To which post would
you like me to respond with a thank you?
 
J

Jay B. Harlow [MVP - Outlook]

Fergus,
I saw the sense in your suggestion ;-)

And as I stated to Scott, it may be what Joe needs.

Note there are ways to structure the Singleton to have an instance & still
present Shared methods to other developers. One of the easiest ways is to
use an inner class. Where the shared methods call methods on an instance of
a inner class object. I did not present them to Joe as I did not want to
scare him too much.

Jay
 
F

Fergus Cooney

Hi Cor,

LOL.

Different interpretations.

'Study a bit more, please'
The speaker is demanding.
I want you to do something.

'I suggest that you study a bit more.'
The speaker is offering.
Here's something you could do.
It's up to you.

That's the 'being-correct-about-English' version.

In the current emotional context, if I added 'please' I would be offering
sarcastic and insincere politeness as shown in that other message. I was
merely being 'pointed' in my tone.

But I believe I hear what you are saying, Cor - "why not start to mend the
rift". It's a worthy suggestion but one that will take some time. It's much
too early for HK and I'm not quite ready yet either.

Regards,
Fergus
 
H

Herfried K. Wagner [MVP]

* "Cor said:

I won't reply to an unqalified post like that written by Fergus. Fergus
is not able to cope with criticism. He always wants to have the last
word... I try to ignore him in future because he doesn't want to be
part of the community. He has chosen to stand outside it.
 
C

Cor

Herfried and Fergus,

Please you both are working for the quality of this newsgroup. And we all
regulars are proud about it that we have such a good newsgroup, without
silly tic tac's .

Sometimes it gives some hard fights to show our ideas and to tell how hard
we stand for it.

But drink after the fight a beer or a wine and say. We both lost and won but
we learned a lot from it.

So let us be proud again.

Cor
 

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