Anulación de la propiedad de sólo lectura en una subclase para que sea lectura / escritura (VB.NET o C #)
-
23-08-2019 - |
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
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