Anulación de la propiedad de sólo lectura en una subclase para que sea lectura / escritura (VB.NET o C #)

StackOverflow https://stackoverflow.com/questions/554369

Pregunta

Esto no parece posible en VB.NET con propiedades ya que la declaración de propiedad en sí debe describir si es ReadOnly o no.

En mi ejemplo a continuación, no me dejó hacer la compilación ReadWriteChild. Creo que podría hacer que el padre de lectura / escritura, y luego tener colocador del ReadOnlyChild no hace nada, pero que parece una especie de hacky. La mejor alternativa parece estar abandonando propiedades en favor de métodos de captador / definidor en este caso.

Public MustInherit Class Parent

    Public MustOverride ReadOnly Property Foo() As String

End Class

Public Class ReadOnlyChild
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            ' Get the Property
        End Get
    End Property

End Class

Public Class ReadWriteChild
    Inherits Parent

    Public Overrides Property Foo() As String
        Get
            ' Get the property.
        End Get
        Set(ByVal value As String)
           ' Set the property.
        End Set
    End Property

End Class
¿Fue útil?

Solución

Dado lo que estamos tratando de lograr, y con el código de ejemplo informados, VB.NET no va a dejar de hacer esto.

Por lo general, se puede declarar una propiedad en VB.NET, así:

Public Class qwqwqw
  Public Property xyz() As String
      Get
          Return ""
      End Get
      Private Set(ByVal value As String)
          '
      End Set
  End Property
End Class

Básicamente marcando la propiedad en general como públicos, pero dando un alcance más restrictiva a la incubadora (o captador).

El principal problema en su caso es el (es decir, resumen) clase base MustInherit. Dado que la propiedad se está definiendo allí se marca como MustOverride, no se puede proporcionar una implementación por defecto (es decir, que, también, es abstracta), y esto incluye la opción "Obtener" y "Ajuste" contornos, por lo tanto, el que sea "global "alcance le da a esta declaración propiedad abstracta, VB.NET le obligará a utilizar este espacio para ambos los captadores y definidores dentro de las clases derivadas.

Tener el calificador de sólo lectura en la propiedad de la clase base que obligará a todas las clases derivadas y las implementaciones de esta propiedad a ser también de sólo lectura. Dejando fuera el calificador de sólo lectura todavía no funcionará, ya que cualquiera que sea el alcance que le das a la propiedad abstracta será el alcance que debe aplicarse tanto a los setters y getters dentro implementaciones derivadas.

Por ejemplo:

Public MustInherit Class Parent
  Public MustOverride Property Foo() As String
End Class

Public Class ReadOnlyChild
  Inherits Parent

  Public Overrides Property Foo() As String
    Get
        '
    End Get
    Private Set(ByVal value As String)
        '
    End Set
  End Property
End Class

(Tenga en cuenta el alcance privado en la incubadora). Esto no funcionará como VB.NET insiste en que ya que estás anulando la propiedad clases base, toda su propiedad debe tener el mismo alcance que el inmueble que anulando (en este caso, público).

El intento de hacer de la propiedad abstracta de la clase base protegida no va a funcionar bien, ya que entonces se verá obligado a aplicar la propiedad en el mismo nivel de alcance, ya que está declarado en su clase base (es decir, protegida). Por lo general, cuando no se anulando definición abstracta de una clase base con un nivel de alcance específico, se puede dar un captador o Setter un más a nivel de evaluación restrictiva, pero no se puede darle un menor a nivel de evaluación restrictiva.

Por lo tanto:

Public MustInherit Class Parent
  Protected MustOverride Property Foo() As String       
End Class

Public Class ReadOnlyChild
  Inherits Parent

  Protected Overrides Property Foo() As String
      Public Get
          '
      End Get
      Set(ByVal value As String)
          '
      End Set
  End Property
End Class

(Tenga en cuenta el alcance público en el captador). No funciona bien debido al alcance del público que es menos restrictivo que el alcance general de la propiedad protegida, y por otra parte, no de la misma a nivel de evaluación según se define en la declaración de propiedad abstracta de la clase base.

Si el diseño de sus clases es como usted menciona en su pregunta, yo personalmente, iría con un captador "al estilo de Java" y setter métodos , ya que entonces se pueden declarar por separado con su propio la determinación del alcance niveles.

Otros consejos

Podría ser una posibilidad remota ... dado que mi conocimiento de VB.NET es mínima ...

En C # se puede especificar la visibilidad de un acceso de propiedad independiente de la propiedad:

public virtual string Name
{
    get { ... }
    protected set { ... }
}

En este ejemplo, las clases hijas pueden acceder a la establecedores, pero otras clases no pueden.

Tenga en cuenta también que las anulaciones pueden tener una mayor visibilidad de lo que anulan - por lo que pueden hacer esto:

public overide string Name
{
    get { ... }
    public set { ... }
}

¿Podría hacer algo como esto en VB.NET?

Compruebe si MrEdmuno es correcto en que se puede utilizar la sombra. Sin embargo, parece que no se puede sombra directamente algo que está marcado MustInherit, por lo que necesita para heredar en una clase (Padre 2) ... luego en el de sólo lectura (en realidad pensar en ello es probable que no necesita utilizar sombras si heredar en una clase)

Creo que mi comentario cuestión sigue en pie, ¿por qué tener que hacer esto? Si ellos son sus propias clases podrían estar mejor para modificar esos, o implementar como una interfaz?

Public MustInherit Class Parent

    Public MustOverride ReadOnly Property Foo() As String

End Class

Public Class ReadOnlyChild
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            'Get the Property
            Return "Return"
        End Get
    End Property

End Class

Public Class Parent2
    Inherits Parent

    Public Overrides ReadOnly Property Foo() As String
        Get
            Return "Return 2"
        End Get
    End Property
End Class

Public Class ReadWriteChild
    Inherits Parent2

    Public Shadows Property Foo() As String
        Get
            '// Get the property.
            Return "2"
        End Get
        Set(ByVal value As String)
            '** Set something
        End Set
    End Property

Por desgracia no tengo el estudio visual de aquí, así que no puedo confirmar.

¿Usted observó el uso de sombras, esto es efectivamente lo mismo que decir "nuevo" en C # declaración de propiedad.

No trate de reemplazar la propiedad, ya que no es virtual. Invalidar los métodos OnReadOnlyChanged y manejar su negocio allí. Buena suerte

Para hacer frente a lo que sugirió Bevan, en VB.NET se puede declarar una propiedad como tener un captador público y un colocador protegida, de la siguiente manera:

Private _ExpectedTotalRoyalties As Decimal

Public Property ExpectedTotalRoyalties() As Decimal
    Get
        Return _ExpectedTotalRoyalties
    End Get
    Protected Set(ByVal value As Decimal)
        If Not _ExpectedTotalRoyalties.Equals(value) Then
            _ExpectedTotalRoyalties = value
            SendPropertyChanged("ExpectedTotalRoyalties")
        End If
    End Set
End Property

Es necesario añadir otro nivel de jerarquía; Por desgracia, la única manera de realmente alcance cosas correctamente es utilizar clases anidadas:

Public Class IntermediateClassForPrivateInheritanceOnly
  Inherits Parent
  Public Overrides ReadOnly Property Foo() As String
  ' etc.
  Private Sub New(whatever)
    MyBase.New(whatever)
  End Sub

  ' Most other stuff for the class goes here.

  Public Class ReadWriteChild
    Inherits IntermediateClassForPrivateInheritanceOnly
    Shadows Property Foo()
    ' etc.
    Public Sub New(whatever)
      MyBase.New(whatever)
    End Sub
  End Class
End Class

Public Class ReadWriteChild  ' Would use an alias, if such things existed
  Inherits IntermediateClassForPrivateInheritanceOnly
  Public Sub New(whatever)
    MyBase.New(whatever)
  End Sub
End Class
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top