Могу ли я иметь функцию с типом возврата самого класса в унаследованных классах?VB.NET - PullRequest
2 голосов
/ 11 декабря 2011

У меня есть родительский класс, который также является фабрикой. Например:

Public Class Factory
    Public Function clone() as Factory
        ' Some logic here
        ' return something
    End Function

    Public Function all() as List (Of Factory)
        ' Some logic here
        ' return something
    End Function
End Class

А потом унаследованный

Public Class BookFactory
    inherits Factory
End Class

Я могу использовать перегиб в классе Factory для генерации правильных расширенных объектов при вызове унаследованным. myBookFactory.clone() вернет экземпляр BookFactory, а не только экземпляр Factory.

Проблема: этот экземпляр BookFactory будет приведен как Factory, поскольку тип функции - Factory, а не BookFactory.

Я бы хотел сделать что-то вроде

Public Class Factory
    Public Function clone() as Me.GetType()
        ' Some logic here
        ' return something
    End Function

    Public Function all() as List (Of  Me.GetType())
        ' Some logic here
        ' return something
    End Function
End Class

Таким образом, возвращаемое значение будет правильно приведено и избегать необходимости делать это каждый раз:

Dim myBookFactory2 = DirectCast(myBookFactory1.clone(), myBookFactory1.getType())

Как я могу это сделать?

Ответы [ 2 ]

2 голосов
/ 11 декабря 2011

Похоже, это вариант запроса ковариантных типов возврата. Как вы заметили, это не поддерживается VB.NET (или C # в этом отношении). Обычно это задается в контексте переопределения виртуальных методов, где это все еще не разрешено. Есть несколько вариантов, каждый со своими плюсами и минусами.

Используйте универсальный аргумент шаблона для указания производного класса

Это похоже на то, как обычно применяется IComparable<T>.

Public Class Factory(Of T As Factory)
    Public Function Clone() As T
        'use GetType(T) to determine derived type
    End Function
End Class

Public Class BookFactory
    Inherits Factory(Of BookFactory)
End Class

Кроме того, если вы можете добавить ограничение New к базовому классу Factory (например: Factory(Of T {New, Factory(Of T)})), вы можете избежать использования отражения.

Однако это не предотвращает случайную (или потенциально злонамеренную) ошибку объявления такого класса:

Public Class EvilFactory
    Inherits Factory(Of BookFactory)
    'hmmm, now clone will be making the wrong type
End Class

Кроме того, этот подход делает невозможным создание списка фабрик разных типов без обращения к другому базовому классу ниже Factory(Of T) или объявления списка как объекта.

Создайте новые методы для производных классов, которые возвращают определенный тип, который вы хотите.

Public Class Factory
    Public Function Clone() As Factory
        'create derived class, but return as base
    End Function
End Class

Public Class BookFactory
    Inherits Factory

    Public Function CloneBooks() As BookFactory
        Return CType(Me.Clone(), BookFactory)
    End Function
End Class

Это позволяет вам скрыть актерский состав для тех случаев, когда вы знаете, что у вас есть BookFactory и хотите получить еще один BookFactory. Это также позволяет полиморфно обрабатывать все типы фабрики в обычном смысле наследования. Однако, если у вас есть объект, напечатанный как Factory, вы все равно получите тип объекта как Factory.

Пересмотреть наследственные отношения

В зависимости от того, как используются эти классы, может не иметь смысла использовать здесь отношения наследования. Если вас беспокоит не перепечатывание кода, вы можете вместо этого заняться генерацией кода.

1 голос
/ 11 декабря 2011

Вы можете потенциально использовать дженерики, чтобы облегчить проблему, но это не снимает требования к касту в какой-то момент. Например:

Public Class Factory(Of T)
    Public Function clone() As Factory(Of T)
        ' Some logic here
        ' return something
    End Function

    Public Function all() As Collections.Generic.List(Of T)
        ' Some logic here
        ' return something
    End Function
End Class

Public Class BookFactory
    Inherits Factory(Of Book)

End Class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...