Я пытаюсь создать класс в VB.NET, который наследовал основной абстрактный класс и также реализует интерфейс. Интерфейс объявляет свойство строки под названием Описание. Базовый класс содержит свойство строки под названием Описание. Основной класс наследовал базовый класс и реализует интерфейс. Существование свойства Description в базовом классе выполняет интерфейсные требования. Это хорошо работает в C#, но вызывает проблемы в VB.NET.
Во-первых, вот пример кода C#, который работает:
public interface IFoo
{
string Description { get; set; }
}
public abstract class FooBase
{
public string Description { get; set; }
}
public class MyFoo : FooBase, IFoo
{
}
Теперь вот версия VB.NET, которая дает ошибку компилятора:
Public Interface IFoo
Property Description() As String
End Interface
Public MustInherit Class FooBase
Private _Description As String
Public Property Description() As String
Get
Return _Description
End Get
Set(ByVal value As String)
_Description = value
End Set
End Property
End Class
Public Class MyFoo
Inherits FooBase
Implements IFoo
End Class
Если я делаю базовый класс (FooBase
) реализуйте интерфейс и добавьте Implements IFoo.Description
к свойству все хорошо, но я не хочу, чтобы базовый класс реализовал интерфейс.
Ошибка компилятора:
Класс 'MyFoo' должен реализовать 'Описание Свойства () Как Строка' для интерфейса 'IFoo'. Свойство Implementing должно иметь соответствие спецификаторам 'Только для записи' или 'Только для чтения'.
VB.NET VB.NET не может обработать это, или я должен изменить свой синтаксис где-нибудь, чтобы заставить это работать?
Вам нужно пометить свое свойство как Overridable
или MustOverride
в базовом классе, а затем вы можете переопределить его в дочернем классе:
Public MustInherit Class FooBase
Private _Description As String
Public Overridable Property Description() As String
Get
Return _Description
End Get
Set(ByVal value As String)
_Description = value
End Set
End Property
End Class
Public Class MyFoo
Inherits FooBase
Implements IFoo
Public Overrides Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class
Изменить Это ответ на сообщение @MA Hanin. Оба наших решения работают, но важно понимать разветвления каждого. Представьте себе следующий код:
Dim X As FooBase = New MyFoo()
Trace.WriteLine(X.Description)
Что получается из X.Description? Используя Overridable, вы получите вызов дочернего класса, а при использовании метода Overload вы получите вызов базового класса. Нет ни правильного, ни неправильного, просто важно понимать последствия заявления. Используя метод Overload, вы должны выполнить преобразование, чтобы получить дочернюю реализацию:
Trace.WriteLine(DirectCast(X, MyFoo).Description)
Если вы просто вызываете MyBase.Description из дочернего класса, вопрос спорный, но если вы когда-нибудь измените определение дочернего класса, вы просто нужно убедиться, что вы понимаете, что происходит.
Это странная проблема, и она ясно показывает разницу между компиляторами C # и VB.NET. Я бы посоветовал вам реализовать интерфейс в абстрактном базовом классе, поскольку это сделает компилятор VB.NET счастливым, и во время выполнения ваш дочерний класс все еще будет иметь метаданные, указывающие на то, что он действительно реализует IFoo
.
Есть ли конкретная причина, по которой дочерний класс должен объявить, что он реализует интерфейс?
Так или иначе, вы должны указать детали реализации интерфейса IFoo.
Как насчет этого простого варианта?
Public Class MyFoo
Inherits FooBase
Implements IFoo
Overloads Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class
VB требует, чтобы реализующее свойство объявляло реализацию. Это связано с тем, что я считаю хорошей особенностью VB, которой мне иногда не хватает в C# - вы можете переименовать член, реализующий член интерфейса.
Таким образом, единственный способ заставить это работать без реализации IFoo. Description
в FooBase
, это объявить Description
Overridable
и затем определить MyFoo
как:
Public Class MyFoo
Inherits FooBase
Implements IFoo
Public Overrides Property Description() As String Implements IFoo.Description
Get
Return MyBase.Description
End Get
Set(ByVal value As String)
MyBase.Description = value
End Set
End Property
End Class