Реализация ToString не переопределяет исходный метод ToString, несмотря на использование Overridable / Overrides. Что мне не хватает? - PullRequest
0 голосов
/ 17 июня 2019

Полагаю, спецификаторы VB Overridable и Overrides не работают так, как я думал.

Есть 3 поколения, от которых наследуются другие классы: Grandfather, Father и TestOverrides.

Public Interface IElements
    Function ToString() As String
End Interface

Public Class Grandfather
    Implements IElements
    Private _MyArg As String
    Public Sub New(Arg As String)
        _MyArg = Arg
    End Sub
    Public Overridable Function IElements_ToString() As String _
        Implements IElements.ToString
        Return _MyArg
    End Function
End Class

Public Class Father
    Inherits Grandfather
    Implements IElements
    Public Sub New(Arg As String)
        MyBase.New(Arg)
    End Sub
    Public Overrides Function IElements_ToString() As String _
        Implements IElements.ToString
        Return MyBase.ToString
    End Function
End Class

Public Class TestingOverrides
    Inherits Father
    Implements IElements
    Public Sub New(Arg As String)
        MyBase.New(Arg)
    End Sub
    Public Overrides Function IElements_ToString() As String _
        Implements IElements.ToString
        Return MyBase.ToString
    End Function
End Class

Их конструктор служит для хранения значения в частном свойстве, а их (переопределенный) метод ToString, реализованный как метод интерфейса, пытается получить это значение.

Module Module1
    Sub Main()
        Dim oTest = New TestingOverrides("x")
        Console.Write(oTest.ToString)
        'produces: SSML.TestingOverrides. Why not "x"?
    End Sub
End Module

Однако отладчик даже не вводит oTest.ToString.Что мне не хватает?

1 Ответ

2 голосов
/ 17 июня 2019

Если вы позвоните через интерфейс, он будет работать:

Sub Main()
    Dim oTest As IElements = New TestingOverrides("x")
    Console.Write(oTest.ToString())
End Sub

Но, если вы вызываете его через тип класса, тогда вы должны использовать имя класса для метода. Поскольку в классе вы объявили его как общедоступный метод с именем IElements_ToString, вам нужно будет вызвать его так:

Sub Main()
    Dim oTest As New TestingOverrides("x")
    Console.Write(oTest.IElements_ToString())
End Sub

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

Как уже упоминали другие ... поскольку все типы автоматически наследуют метод ToString, необычно, неожиданно и запутанно определять другой интерфейс с таким же именем через интерфейс. Было бы лучше назвать его как-нибудь еще, например GetValue или GetDescription, или просто доверить всем производным классам переопределение метода Object.ToString. Если вы действительно хотите, чтобы все производные классы обеспечивали реализацию ToString, вы можете сделать это через реализацию класса Grandfather:

Public Class Grandfather
    Implements IElements
    Private _MyArg As String
    Public Sub New(Arg As String)
        _MyArg = Arg
    End Sub
    Public NotOverridable Overrides Function ToString() As String _
        Implements IElements.GetArg
        Return _MyArg
    End Function
End Class

Или:

Public Class Grandfather
    Implements IElements
    Public NotOverridable Overrides Function ToString() As String 
        Return GetArg()
    End Function

    Public MustOverride Function GetArg() Implements IElements.GetArg
End Class
...