Есть ли способ сделать значение доступным только для родителя вложенного класса VB.NET?

В целом, согласно парадигме ООП, мое понимание инкапсуляции в основном говорит:

  1. Если член является закрытым, доступ к нему может получить только класс.
  2. Если член защищен, к нему может получить доступ только базовый класс и любые производные классы.
  3. Если член является общедоступным, доступ к нему может получить любой.

Если у меня есть вложенный класс, могу ли я объявить свойство доступным только для этого класса и родительского класса, в который оно вложено? Например:

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

В этом примере я не могу получить прямой доступ к myNestedObject.myInt или myNestedObject.myDbl из экземпляра ContainerClass, если эти члены являются частными или защищенными. Но предположим, я не хочу делать их общедоступными, потому что тогда они СЛИШКОМ открыты: их можно изменить откуда угодно, а не только внутри объекта ContainerClass. Объявление их друзьями все равно было бы слишком слабым, поскольку это позволило бы изменять их из любого места в приложении.

Есть ли способ выполнить то, что я собираюсь сделать здесь? Если нет, может ли кто-нибудь придумать более разумный способ добиться чего-то подобного?


person Dan Tao    schedule 24.06.2009    source источник


Ответы (2)


Невозможно сделать это напрямую с помощью комбинации модификаторов доступности.

Лучший способ, который я могу придумать, заключается в следующем. Это включает в себя дополнительный уровень косвенности.

  • Создайте вложенный интерфейс с приватным доступом. Это даст доступ только родительскому классу и вложенным дочерним элементам.
  • Добавьте поля, к которым вы хотите получить доступ к этому интерфейсу
  • Заставьте класс Nested реализовать интерфейс
  • Сделайте так, чтобы все реализации имели частный доступ

Теперь родительский класс и только родительский класс будет иметь доступ к этим свойствам и методам.

Например:

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
person JaredPar    schedule 24.06.2009
comment
Это предложение кажется мне многообещающим. Я попробую. - person Dan Tao; 24.06.2009
comment
Хороший. Вы показываете мне новое (теоретическое?) использование интерфейсов. +1 :) - person Sylvain Rodrigue; 24.06.2009

Основываясь на ответе JaredPar, вы можете использовать частный дочерний класс, но общедоступный интерфейс, который показывает только то, что он должен показывать:

    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

Использование :

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