Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Visual Inheritance - Overriding in subclass problem 1

Status
Not open for further replies.

bernardmanning

Programmer
Oct 14, 2003
61
GB
Hi,

I'm a long time foxpro programmer whos pretty new to vb.net and I'm having a little difficulty when trying to override method code in classes.

What I'm attempting to do is to create a class library of user controls for re-use throughout my application. My problem occurs when I try to override method code at an instance level..

eg I've created a parent class library that contains various controls, commandbuttons, labels , textboxes. These I've created visually using the designer.

In my parent library I have a commandbutton which has a click method that looks like this ;

Code:
Public Overridable Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BaseButton.Click
        MsgBox("parent click")
    End Sub

I then build the class library , start a new windows project and add a reference to my class to toolbar, ie, view / toolbar / add/remove items, i browse to my class dll and add it and my controls appear on the toolbox ok.

I create a new windows form and drop my commandbutton onto the form.

If I run the form, click the button , I see the msgbox containing the "parent click" string..

So far so good...

My problem comes when I try to override the click method on the instance of the commandbutton on the form.

If I try this ;

Code:
Public Overrides Sub BaseCommandButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BaseCommandButton1.Click
        MsgBox("subclassed")
End Sub

then I get an error message telling me that ;

Code:
C:\VB.NetTest\WindowsApplication2\SubClassedForm.vb(76): sub 'BaseCommandButton1_Click' cannot be declared 'Overrides' because it does not override a sub in a base class.

I've tried recreating my parent classes using code rather than the visual designer with the same result..

I'd be grateful if anybody could give me any clues as to what is going on with this pretty basic piece of OOP...

Many Thanks, Bernard
 
In order for one sub to override another sub they have to be in parent/child classes and have the same name and signature.

This this case, your two subs have different names, so there is nothing to over ride.

Also, are the subs in both cases are methods of the form, and not the button? If so then there is no inheritance of that sub in the button class.

-Rick

----------------------
 
Hi Rick

Thanks for the reply, I had similar thoughts to yourself, but even changing the controls names so that the names and methods match still gives me the same problem.

The signatures of the methods also match, otherwise I would have to mark them as 'overloadable'...

Changing it to ...

The parent class code :-

Code:
Public Overridable Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BaseButton.Click
        MsgBox("parent click")
End Sub

and the subclassed child

Code:
Private Overrides Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BaseButton.Click
        MsgBox("subclass click")
End Sub

still doesn't work.

Bear in mind that these are classed controls, so many subclasses of the same parent class could be on the same form, so the subclasses would have different names ...

cmdbutton1 , cmdbutton2 etc....

What I'm trying to do here is to be able to drop a classed control onto a form , possibly multiple times so that they all have the same appearence and inherit the same code.

However sometimes I would want to override a method or two in some cases on the subclass...

Any ideas???

Bernard...


 
Bernard,

There are few issues I see here

1. If your intention is to override a base class Sub, don't know how you got the name of the control changed from BaseButton to BaseCommandButton1. Because your can/will not be able change the Name property of a control in the descendant.

So your code should have been like

Code:
Ancestor

Public Overridable Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles BaseButton.Click

        MessageBox.show("parent click")
End Sub

In descendant

Public Overrides Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 

        MessageBox.show("child click")
End Sub

Notice that I have omitted the clause Handles BaseButton.Click in the child. This is because if you give the Handles clause both on ancestor and descendant, the same sub from the child will be triggered twice if you click on that button in child form.

2. As a better OOP concept, instead of Public use Protected where ever possible. Thumb rule is avoid using least restrictive and always try using most restrictive and liberalize the access wherever necessary.


-Kris
 
Bernard,

I think I was little slow submitting my last post, anyway your new code also won't work because you can not make an overridable Sub/Function more restrictive than the ancestor. Here in your ancestor you declared it as Public and in the descendant you are trying to make it Private that won't work and that is what I have explained in #2 of my last post. While overriding a Sub/Function you can keep the same access modifier from the ancestor or you can use least restrictive than the current not more restrictive. So as an example you can make a sub go from Protected to Public not vice versa. Hope this explains your question.


-Kris
 
Hi Guys,

thanks for your patience and help with this problem...

I do seem to making a little progress, but I wonder if the problems I seeing is that I'm not grasping some basic concept..so if you could bear with me while I try to confirm some thing...

Imagine I've got a CommandButton Class that is going to be my application base class and it looks something like this :-

Code:
Public Class BaseCommandButton
    Inherits System.Windows.Forms.UserControl

    Public Overridable Sub MyClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BaseButton.Click
        MessageBox.Show("parent click")
    End Sub

End Class

now I can now subclass this and override this method by creating an instance of this class within another class..eg

Code:
Public Class myButton
    Inherits BaseClasses.BaseCommandButton

    Public Overrides Sub MyClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        MsgBox("my subclassed child yeah")
    End Sub
End Class

I can now drop this control on my form and it works fine...

What I was wanting to do is, not have create the class above but drop an instance of the parent on the form and then override the MyClick method on the form itself.

Is it possible to do this?

I seem to be having problem as the my subclassed MyClick method ends up getting associated with the form and not the button.

I think this is the root of my problems...

Again many thanks for the continued help, Bernard




 
Maybe something like this:

Code:
Public Class btnTest
  Inherits System.Windows.Forms.Button

  Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
    ProcessClick()
  End Sub

  Protected Sub ProcessClick()
    'Enter default code here
  End Sub
End Class

that will create a button object that has the click event handled internally. But you won't be able to adapt the click event on other forms.

What exactly is your purpose? I'm not sure if this is going in the direction you are looking for.

Are you trying to add base functionality to a button? or a form? The button raises an event. The form has a sub that handles that event. If you are looking for added functionality you will want to inherit the button and add your functionality to it. If you are looking for reusability you may want to create a base for with generic buttons. In my current project we have default forms with OK and Cancel buttons that call overridable sub (ProcessOK, ProcessCancel).

-Rick

----------------------
 

Hi Rick

at a very basic level I'm trying to create a template base class library of controls.

For example,this class would contain a BaseCommandButton class directly descended from the .net base commandbutton

Also in the library I would have subclasses descended from the BaseCommandButton, say BaseOKCommandButton, baseCancelButton.

These would inherit the property but may different captions and some default code in the click events etc.

This is ok,

The problem I've got is that say I drop my BaseOKCommandButton on a form.

When the user clicks the button I need to do something at an instance level before calling the default parent class code.

is it possible to add code to the click event of my BaseOKCommandButton at an instance level on a form?

or do I need to store my button in another class, change the click event and drop that class on my form?

again, many many thanks for your continued help....

Bernard

 
You can try something like

Code:
Ancestor

Public Overridable Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles BaseButton.Click

        MessageBox.show("parent click")
End Sub

In descendant

Public Overrides Sub BaseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 

 //Add code/calls here to do the process that the    
 //child need to do

 //Call the parent event
 MyBase.BaseButton_Click(sender, e)
End Sub

here thru MyBase you can access base class implementation. Hope this is what you are looking for...

-Kris
 
Or another option:

in the form you intend to inherit from
Code:
  Private Sub btnOK_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs)
                          Handles btnOk.Click
    'Add your generic base code here
    Call ProcessOK()
  End Sub

  Protected Overridable Sub ProcessOK()
    'default code
    Me.Close()
  End Sub


Then in the form that you are useing (The one that inherits from the form above)

Code:
  Protected Overrides Sub processok()
    'do specific functionality here
  End Sub


That way, you can have a generic set of code that is always fired (in the parent class) a set of default code (in the parent class) and a set of override code (in the child class)

-Rick

----------------------
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top