У меня есть иерархия классов/интерфейсов. На стороне интерфейса у меня естьИспользование вывода типа с текущими интерфейсами
IQuery
ISelect (inherits IQuery)
IUpdate (inherits IQuery)
etc
На стороне класса у меня есть
QueryBase (implements IQuery)
SelectQuery (implements ISelect)
UpdateQuery (implements IUpdate)
etc
Очевидно, например, как обновление и выберите классы совместно ИНЕКЕ, но только Select имеет GROUP BY функциональность настолько идеально если создается запрос обновления, свободный интерфейс не даст доступа к функциональности GROUP BY, но будет работать, если будет создан SelectQuery.
, например, в плавных терминах интерфейса
var/Dim select = New SelectQuery() <- returns ISelect explicit
.AddColumn(....) <- returns ISelect explicit
.AddWhere(....) <- returns ISelect inferred
.AddGroupBy(....) <- returns ISelect explicit
var/Dim update = New UpdateQuery() <- returns IUpdate explicit
.AddSet(....) <- returns IUpdate explicit
.AddWhere(....) <- returns IUpdate inferred
Я не уверен, как реализовать функцию AddWhere.
Ранее я объявил функцию AddWhere в интерфейсе IQuery, как
Function AddWhere(ByVal condition As ICriterion) As IQuery
IQuery AddWhere(ICriterion condition)
, но потому, что он возвращался в IQuery, я теряла преимущество умозаключения типа и поэтому, как только беглый интерфейс был брошен для IQuery, если это был созданный запрос Select, у меня больше не будет доступа к, например, методу AddGroupBy.
Так что я попытался реализовать его как метод расширения с обобщениями
<Extension>
Public Function AddWhere(Of T As IQuery)(Byval this as T, Byval condition as Condition) as T
this.SetWhere(condition)
Return Me
End Function
public T AddWhere<T>(T @this, Condition condition) where T : IQuery
{
@this.SetWhere(condition);
return this;
}
с (внутренним) методом, SetWhere друга, на QueryBase разрешить мне обновить ИНЕК. Однако, поскольку общий параметр ограничен IQuery, он не найдет SetWhere. Однако, если я ограничусь как QueryBase, то, очевидно, компилятор бросает wobblies, говоря, что ISelect не может найти метод AddWhere.
Я думаю, что я не совсем понял цепочку наследования или реализации интерфейса, совершенно подходящую для того, чего я пытаюсь достичь.
(я надеюсь, что это понятно !!)
Я бы признателен, если кто-то может предложить либо где я неправильно с точки зрения реализации метода расширения, или как я должен лучше структурировать мой класс/интерфейс иерархия.
Я думаю http://stackoverflow.com/questions/1723648/how-to-inherit-method-but-with-different-return-type может быть полезно прочитать, поскольку он обсуждает упрощенную форму того, что вы пытается. В основном это говорит о том, что это невозможно, хотя есть несколько обходных решений, включая создание базовых классов Generic. Я думаю, что эта последняя часть (ответ dtb), вероятно, сделает то, что вы хотите, если вы довольны реструктуризацией вашего кода. – Chris
Крис: Я немного поиграл с этим. Это q говорит только о конкретных классах, и мне интересно, сложна ли моя сценария иерархией интерфейса.Я попытался обобщить QueryBase на QueryBase (из T как IQuery), но это означало бы, что AFYICS, что мой, например, «фабрика SelectQuery», должен был бы вернуть либо SelectQuery, либо QueryBase (из ISelect), а не ISelect. Аналогичным образом, беглым методам необходимо будет возвращать бетоны. Я возвращал чистые интерфейсы из-за ISP/простоты насмешек. Я что-то упускаю? –
Боюсь, я не знаю. Я знаю, что вопрос был несколько иным и нуждался в некоторой адаптации, если бы он работал, но я этого не делал раньше, и у меня нет времени играть с ним сам. Возможно, эти вопросы не помогут вам решить все, я просто надеялся. ;-) – Chris