locked
Sub class change the container Class RRS feed

  • Question

  • I have a Class cA containing some values.

    The Class cB have a member of type cA. 

    I would like to have a sub in the class cA changing a value in the containing cB, if cA a value are changed. 

    Like:

    Public Class cA

        Private _V

        Public Property V As Integer

            Get

                V = _V

            End Get

            Set(V As Integer)

                _V = V

                '  set the dirty in cB to true

            End Set

        End Property

        Public Sub New()

            '  set the dirty in cB to true

        End Sub

    End Class

    Public Class cB

        Public Property aA As cA

        Public Property dirty As Boolean

    End Class

    Is it possible to design the classes like that?

    What if cB contains a collection of cA’s?

    Friday, December 14, 2012 12:25 PM

Answers

  • Public Class cA
     
        Private _V
        Public Property cC As cB
     
        Public Property V As Integer
     
            Get
     
                V = _V
     
            End Get
     
            Set(V As Integer)
     
                _V = V
     
                '  set the dirty in cB to true
                 cC.dirty = True
     
            End Set
     
        End Property
     
        Public Sub New()
     
            '  set the dirty in cB to true
               cC.dirty = True
     
        End Sub
     
    
    End Class
     
    Public Class cB
     
        Public Property aA As cA
     
        Public Property dirty As Boolean
     
    End Class
    
    Let me know if you want something else .

    One good question is equivalent to ten best answers.

    • Marked as answer by hjl1 Monday, December 17, 2012 12:08 PM
    Friday, December 14, 2012 12:36 PM
  • This can get into a lot of design theory, and while there may be no absolute answer, I believe the following information is generally what should be followed when designing with OOP in .Net.

    In general, we want to have loosely coupled objects in our domain (a domain is simply a logical container of related objects).  While the example provided by bootstrap2 would certianly work, it uses a tightly coupled design where ClassA must know directly about ClassB.

    The other thing to consider is that an object should own its work.  In this case, you want ClassB to be able to modifiy one of its member values based on actions that may occur in one or more instances of ClassA contained within ClassB.  So really, ClassA should not be responsible for making any modifications to the member value of ClassB.  All ClassA should do is announce that one of its own values has changed.  It is then up to anyone listening for this announcement to do whatever they need to do in response.  That is the event-driven model.

    .Net already provides us with a mechanism for doing this with INotifyPropertyChanged.  We can implement this interface in ClassA and then ClassB can subscribe to the event on any instances of ClassA that it might contain.

    Public Class cA
        Implements System.ComponentModel.INotifyPropertyChanged
     
        Private _V
        Public Property V As Integer
            Get
                V = _V
            End Get
            Set(V As Integer)
                _V = V
                OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("V"))
            End Set
        End Property
     
        Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
     
        Protected Overridable Sub OnPropertyChanged(e As System.ComponentModel.PropertyChangedEventArgs)
            RaiseEvent PropertyChanged(Me, e)
        End Sub
    End Class
     
    Public Class cB
        Private _aA As cA
        Public Property aA As cA
            Get
                Return _aA
            End Get
            Set(value As cA)
                If Not value Is _aA Then
                    If _aA IsNot Nothing Then
                        RemoveHandler _aA.PropertyChanged, AddressOf cA_PropertyChanged
                    End If
                    _aA = value
                    dirty = True
                    If value IsNot Nothing Then
                        AddHandler _aA.PropertyChanged, AddressOf cA_PropertyChanged
                    End If
                End If
            End Set
        End Property
     
        Public Property dirty As Boolean
     
        Private Sub cA_PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs)
            If e.PropertyName = "V" Then
                dirty = True
            End If
        End Sub
    End Class
     

    If you had a list of ClassB instead of a single value property, you would add and remove handlers whenever items were added or removed from the list (probably by creating a custom collection of ClassA to manage the handlers for you).


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


    • Edited by Reed KimbleMVP, Moderator Friday, December 14, 2012 3:43 PM fixed code sample
    • Marked as answer by hjl1 Tuesday, December 18, 2012 5:10 AM
    Friday, December 14, 2012 3:33 PM
    Moderator

All replies

  • Public Class cA
     
        Private _V
        Public Property cC As cB
     
        Public Property V As Integer
     
            Get
     
                V = _V
     
            End Get
     
            Set(V As Integer)
     
                _V = V
     
                '  set the dirty in cB to true
                 cC.dirty = True
     
            End Set
     
        End Property
     
        Public Sub New()
     
            '  set the dirty in cB to true
               cC.dirty = True
     
        End Sub
     
    
    End Class
     
    Public Class cB
     
        Public Property aA As cA
     
        Public Property dirty As Boolean
     
    End Class
    
    Let me know if you want something else .

    One good question is equivalent to ten best answers.

    • Marked as answer by hjl1 Monday, December 17, 2012 12:08 PM
    Friday, December 14, 2012 12:36 PM
  • This can get into a lot of design theory, and while there may be no absolute answer, I believe the following information is generally what should be followed when designing with OOP in .Net.

    In general, we want to have loosely coupled objects in our domain (a domain is simply a logical container of related objects).  While the example provided by bootstrap2 would certianly work, it uses a tightly coupled design where ClassA must know directly about ClassB.

    The other thing to consider is that an object should own its work.  In this case, you want ClassB to be able to modifiy one of its member values based on actions that may occur in one or more instances of ClassA contained within ClassB.  So really, ClassA should not be responsible for making any modifications to the member value of ClassB.  All ClassA should do is announce that one of its own values has changed.  It is then up to anyone listening for this announcement to do whatever they need to do in response.  That is the event-driven model.

    .Net already provides us with a mechanism for doing this with INotifyPropertyChanged.  We can implement this interface in ClassA and then ClassB can subscribe to the event on any instances of ClassA that it might contain.

    Public Class cA
        Implements System.ComponentModel.INotifyPropertyChanged
     
        Private _V
        Public Property V As Integer
            Get
                V = _V
            End Get
            Set(V As Integer)
                _V = V
                OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("V"))
            End Set
        End Property
     
        Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
     
        Protected Overridable Sub OnPropertyChanged(e As System.ComponentModel.PropertyChangedEventArgs)
            RaiseEvent PropertyChanged(Me, e)
        End Sub
    End Class
     
    Public Class cB
        Private _aA As cA
        Public Property aA As cA
            Get
                Return _aA
            End Get
            Set(value As cA)
                If Not value Is _aA Then
                    If _aA IsNot Nothing Then
                        RemoveHandler _aA.PropertyChanged, AddressOf cA_PropertyChanged
                    End If
                    _aA = value
                    dirty = True
                    If value IsNot Nothing Then
                        AddHandler _aA.PropertyChanged, AddressOf cA_PropertyChanged
                    End If
                End If
            End Set
        End Property
     
        Public Property dirty As Boolean
     
        Private Sub cA_PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs)
            If e.PropertyName = "V" Then
                dirty = True
            End If
        End Sub
    End Class
     

    If you had a list of ClassB instead of a single value property, you would add and remove handlers whenever items were added or removed from the list (probably by creating a custom collection of ClassA to manage the handlers for you).


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


    • Edited by Reed KimbleMVP, Moderator Friday, December 14, 2012 3:43 PM fixed code sample
    • Marked as answer by hjl1 Tuesday, December 18, 2012 5:10 AM
    Friday, December 14, 2012 3:33 PM
    Moderator
  • Good idea!

    It will solve my problem.

    Thanks

    Monday, December 17, 2012 12:08 PM