none
Access Derived Class Members From Base Class RRS feed

  • Question

  • I have a user control called Products that is inherited by several derived classes.

    Public Class Products
        Protected Overridable Property ProductType As ????
    
        Protected Sub PopulateProductControls()
    
            For Each ctrl As Control In Me.ProductType.Controls
                ' do stuff
            Next ctrl
    
        End Sub
    End Class
    
    Public Class ItemA
        Inherits Products
        Protected Property ProductCode As String = "A"
        Protected Overrides Property ProductType As ItemA = Me
    End Class
    
    Public Class ItemB
        Inherits Products
        Protected Property ProductCode As String = "B"
        Protected Overrides Property ProductType As ItemB = Me
    End Class
    
    Public Class ItemC
        Inherits Products
        Protected Property ProductCode As String = "C"
        Protected Overrides Property ProductType As ItemC = Me
    End Classs


    Each product (ItemA, ItemB, ItemC) contain controls and properties that I would like to access from my base class (Products) code.  The problem is at runtime my base class doesn't know what the derived classes type is.  How can I do this?  For example, how access the derived classes controls in the PopulateProductControls() method?



    Ryan


    • Edited by Ryan0827 Friday, June 6, 2014 4:10 PM
    Friday, June 6, 2014 4:02 PM

Answers

  • As Reed said, the parent class can't know anything about the child classes other than what the child classes inherit from the parent. So the properties of each child that are the same, should really be moved into the parent class. Or you could use an interface on the child classes to require certain properties to be there, and then in the parent class you can cast the child class to the interface type. How you go about doing this really depends on the requirements of the program.

    Matt Kleinwaks - MSMVP MSDN Forums Moderator - www.zerosandtheone.com

    Friday, June 6, 2014 6:04 PM
    Moderator
  • It doesn't work that way.  The base class cannot know anything about members of a derived class.

    You also may have complicated things for yourself by tightly coupling the user control to the model object.  You probably want Products, ItemA, ItemB, etc to all be classes (not controls) and then have a single control that can work with any derived Products object or inherited controls for each specific product type (point is that the product object and the control which manipulates it are two separate entities).

    Can you mock up a small usage example (pusedo code would be fine) that shows what you are ultimately trying to achieve?


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Friday, June 6, 2014 4:14 PM
    Moderator
  • In my perception is what you ask standard OOP. You can always reach a control by using its base class, as long as it is about properties inside the base class. A well known sample is windows forms, where we mostly use the base class instead of the derived class.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim textbox1 As New TextBox
            Dim combobox1 As New ComboBox
            Controls.Add(textbox1)
            Controls.Add(combobox1)
            Dim top As Integer
            For Each ctr As Control In Controls
                top += 20
                ctr.Top = top
                ctr.Width = 70
                ctr.Height = 10
            Next
        End Sub
    End Class


    Success
    Cor


    Monday, June 9, 2014 2:39 PM

All replies

  • It doesn't work that way.  The base class cannot know anything about members of a derived class.

    You also may have complicated things for yourself by tightly coupling the user control to the model object.  You probably want Products, ItemA, ItemB, etc to all be classes (not controls) and then have a single control that can work with any derived Products object or inherited controls for each specific product type (point is that the product object and the control which manipulates it are two separate entities).

    Can you mock up a small usage example (pusedo code would be fine) that shows what you are ultimately trying to achieve?


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Friday, June 6, 2014 4:14 PM
    Moderator
  • As Reed said, the parent class can't know anything about the child classes other than what the child classes inherit from the parent. So the properties of each child that are the same, should really be moved into the parent class. Or you could use an interface on the child classes to require certain properties to be there, and then in the parent class you can cast the child class to the interface type. How you go about doing this really depends on the requirements of the program.

    Matt Kleinwaks - MSMVP MSDN Forums Moderator - www.zerosandtheone.com

    Friday, June 6, 2014 6:04 PM
    Moderator
  • Hi Reed and Kleinma, hope you had a nice weekend.

    I've never implemented an interface before, but I did some reading over the weekend and it does seem like maybe an option.  However, I'm not sure how I can cast a derived class to the interface type in the base class as you suggested?  I'll try to illustrate my ultimate goal and hopefully that will help determine the best solution.

    I am building program that our sales team can use to quote our products.  So I built a user control called Products that will host all the different product classes.  For example, ItemA will have several checkboxes, comboboxes, textboxes, etc that will be used to quote ItemA.  Below is the Products user control I built, all the item controls will be placed to the left of the grey panel.

    I figure I would use my Products base class to store properties such as a parts list and product code that will be used to quote the various items.  It would also have methods to handle the retrieval and saving of quotes parts from & to the database.  Currently, I setup all these properties and methods in the base class and reference them in my derived class like so:

    Public Class LineItemManager
    
        Private _PartList As New dsProductParts
    
        Protected Property LineItemTag As LineItemTag
        Protected Property QuoteManager As QuoteManager
        Protected Property QuotedParts As DataTable
        Protected Property ProductCode As String
        Protected Property ProductControlsToSave As List(Of Control)
    
        Protected ReadOnly Property PartList() As dsProductParts
            Get
                Return Me._PartList
            End Get
        End Property
    
        Protected Sub New()
            ' This call is required by the designer.
            InitializeComponent()
    
        End Sub
    
        Protected Sub New(ByRef LineItemTag As LineItemTag)
    
            ' call this constructor from the LineItemTag edit button
    
            InitializeComponent()
    
            Me.LineItemTag = LineItemTag
            Me.QuoteManager = LineItemTag.QuoteManager
    
            ' get quoted parts from database
            Me.PopulateProductControls()
    
            ' get all the parts required by the product to get a price
            Me.SetAllProductParts()
    
        End Sub
    
        Protected Sub New(ByRef QuoteManager As QuoteManager)
    
            ' this constructor is called from the QuoteManager product button, because it is a new item and no LineItemTag has been created yet
    
            InitializeComponent()
    
            Me.LineItemTag = Nothing
            Me.QuoteManager = QuoteManager
    
            ' get all the parts required by the product to get a price
            Me.SetAllProductParts()
    
        End Sub
    
        Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
            ' save derfived class control values to database
            Me.Dispose()
        End Sub
    
        Private Sub SetAllProductParts()
            ' fill _PartList dataset
        End Sub
    
        Protected Sub PopulateProductControls()
            ' gets saved derived class control values from database and assigns values to derived class controls in the ProductControlsToSave list
        End Sub
    
    End Class
    
    
    Public Class LEDBillboard
        Inherits LineItemManager
    
        Public Sub New(ByRef LineItemTag As LineItemTag)
    
            MyBase.New(LineItemTag)
    
            ' This call is required by the Windows Form Designer.
            InitializeComponent()
    
        End Sub
    
        Public Sub New(ByRef QuoteManager As QuoteManager)
    
            MyBase.New(QuoteManager)
    
            ' This call is required by the Windows Form Designer.
            InitializeComponent()
    
        End Sub
    
        Private Sub LEDBillboard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
    
            MyBase.ProductCode = "LB"
    
            ' build a collection of individual controls that need to be saved in database
            With MyBase.ProductControlsToSave
                .Add(Me.Textbox1)
                .Add(Me.ComboBox1)
                .Add(Me.Checkbox1)
            End With
    
        End Sub
    
    End Class

    But the problem I foresee in the future is what if I need to add a new ItemZ 1 year from now, I will have to remember to write code to set all the properties of the base class in my derived class.  It would be convenient if I could declare Products class in such a way that during design time I would be reminded to code the properties of the derived class.  For example, declare Products properties as MustOverride, but I can't do that because I have to declare Products as MustInherit which can't be done because the designer can't create an instance of an abstract class.  Is this where an Interface would be useful?

    I hope this makes sense. :)


    Ryan

    Monday, June 9, 2014 2:04 PM
  • In my perception is what you ask standard OOP. You can always reach a control by using its base class, as long as it is about properties inside the base class. A well known sample is windows forms, where we mostly use the base class instead of the derived class.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim textbox1 As New TextBox
            Dim combobox1 As New ComboBox
            Controls.Add(textbox1)
            Controls.Add(combobox1)
            Dim top As Integer
            For Each ctr As Control In Controls
                top += 20
                ctr.Top = top
                ctr.Width = 70
                ctr.Height = 10
            Next
        End Sub
    End Class


    Success
    Cor


    Monday, June 9, 2014 2:39 PM