Pregunta

En general, según el paradigma OOP, mi comprensión de la encapsulación básicamente dice:

  1. Si un miembro es privado, solo la clase puede acceder a él.
  2. Si un miembro está protegido, solo puede acceder a él la clase base y cualquier clase derivada.
  3. Si un miembro es público, cualquiera puede acceder a él.

Si tengo una clase anidada, ¿puedo declarar que una propiedad sea accesible solo para esa clase y la clase principal en la que está anidada? Por ejemplo:

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

En el ejemplo, no puedo acceder directamente a myNestedObject.myInt o myNestedObject.myDbl desde una instancia de ContainerClass si esos miembros son privados o protegidos. Pero supongamos que no quiero hacerlos públicos, porque entonces están DEMASIADOS expuestos: pueden modificarse desde cualquier lugar, no solo dentro de un objeto ContainerClass. Declararlos como amigos aún sería demasiado débil, ya que eso les permitiría modificarlos desde cualquier lugar dentro de la aplicación.

¿Hay alguna forma de lograr lo que estoy buscando aquí? Si no, ¿alguien puede pensar en una forma más sensata de lograr algo como esto?

¿Fue útil?

Solución

No hay forma de hacerlo directamente con una combinación de modificadores de accesibilidad.

La mejor forma en que puedo pensar en hacer esto es la siguiente. Implica un nivel adicional de indirección.

  • Crear una interfaz anidada con accesibilidad privada. Esto solo dará acceso a la clase Parent y a los hijos anidados
  • Agregue los campos a los que desea acceder a esa interfaz
  • Hacer que la clase Nested implemente la interfaz
  • Hacer que todas las implementaciones tengan accesibilidad privada

Ahora la clase padre y solo la clase padre tendrán acceso a esas propiedades y métodos.

Por ejemplo:

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

Otros consejos

Basado en la respuesta de JaredPar, podría usar una ChildClass privada pero una interfaz pública que revela solo lo que debería mostrar:

    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

Uso:

Dim c As ParentClass.IChildClass = ParentClass.GetNewChild()
MessageBox.Show(c.i)
c.i = 2 ' Does not compile !
c.SomeSub()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top