views:

116

answers:

2

In general, according to the OOP paradigm, my understanding of encapsulation basically says:

  1. If a member is private, it can only be accessed by the class.
  2. If a member is protected, it can only be accessed by the base class and any derived classes.
  3. If a member is public, it can be accessed by anyone.

If I have a nested class, can I declare a property to be accessible only to that class and the parent class it's nested within? For example:

Public Class ContainerClass
    Public Class NestedClass
        Protected myInt As Integer ' <- this is what I am wondering about '
        Protected myDbl As Double ' <- this is what I am wondering about '

        Sub New()
            myInt = 1
            myDbl = 1.0
        End Sub
    End Class

    Private myNestedObject As New NestedClass

    ' this function is illegal '
    Public Sub GrowNestedObject(ByVal multiplier As Integer)
        myNestedObject.myInt *= multiplier
        myNestedObject.myDbl *= multiplier
    End Sub
End Class

In the example, I cannot directly access myNestedObject.myInt or myNestedObject.myDbl from an instance of ContainerClass if those members are Private or Protected. But suppose I don't want to make them Public, because then they are TOO exposed: they can be altered from anywhere, not just within a ContainerClass object. Declaring them Friend would still be too weak as that would allow them to be altered from anywhere within the application.

Is there any way to accomplish what I am going for here? If not, can anyone think of a more sensible way to achieve something like this?

+4  A: 

There is no way of doing this directly with a combination of accessibility modifiers.

The best way I can think of doing this is as follows. It involves an extra level of indirection.

  • Create a Nested Interface with Private accessibility. This will give only the Parent class and nested children access
  • Add the fields you want access to to that interface
  • Make the Nested class implement the interface
  • Make all of the implementations have private accessibility

Now the parent class and only the parent class will have access to those properties and methods.

For Example:

Class Parent
    Private Interface Interface1
        ReadOnly Property Field1() As Integer
    End Interface

    Public Class Nested1
        Implements Interface1

        Private ReadOnly Property Field1() As Integer Implements Interface1.Field1
            Get
                Return 42
            End Get
        End Property
    End Class

    Sub New()
        Dim child As Interface1 = New Nested1
        Dim x = child.Field1
    End Sub
End Class
JaredPar
This suggestion sounds quite promising to me. I'll try it out.
Dan Tao
Nice. You show me a new (theorical ?) usage of interfaces. +1 :)
Sylvain
A: 

Based on JaredPar's answer, you could use a Private ChildClass but a Public Interface that reveals only what it sould show :

    Public Class ParentClass

        Public Interface IChildClass
            ReadOnly Property i() As Integer
            Sub SomeSub()
        End Interface

        Private Class ChildClass
           Implements IChildClass
           Public myInt As Integer 

           Public ReadOnly Property i() As Integer Implements IChildClass.i
               Get
                   Return myInt
               End Get
           End Property

           Public Sub SomeSub() Implements IChildClass.SomeSub
           End Sub
        End Class

    Public Shared Function GetNewChild() As IChildClass
        Dim myChild = New ChildClass()
        myChild.myInt = 3
        Return myChild
    End Function
End Class

Usage :

Dim c As ParentClass.IChildClass = ParentClass.GetNewChild()
MessageBox.Show(c.i)
c.i = 2 ' Does not compile !
c.SomeSub()
Sylvain