我想用抽象的getter Command
声明一个基类GetValue
。然后我将其子类化为TalkCommand
和SpendCommand
,例如。
这两个类都必须实现GetValue
,但是,我希望TalkCommand
为string
返回GetValue
类型(要说什么?),我希望{{1}返回SpendCommand
类型。 (花多少钱?)
我不知道如何在int
基类中编写它。这种设计在C#中是否可行?
答案 0 :(得分:3)
In addition to Manfred's answer,我想给你一个进一步的提示。
虽然泛型为您提供了定义GetValue
返回类型的有用工具,但您无法执行以下向上转换:
abstract class Command<T>
{
public abstract T GetValue();
}
class TalkCommand : Command<string>
{
public override string GetValue()
{
return "Test";
}
}
// TalkCommand isn't Command<object>
Command<object> cmd = new TalkCommand();
我不会将您的命令定义为抽象类,而是开始将其定义为covariance的接口:
public interface ICommand<out T>
{
T GetValue();
}
整个抽象类可以实现ICommand<out T>
:
abstract class Command<T> : ICommand<T>
{
public abstract T GetValue();
}
现在,您可以将ICommand<string>
的实施转发为ICommand<object>
:
ICommand<string> cmd = new TalkCommand();
ICommand<object> cmd2 = cmd;
这很好,因为你可以获得两个世界中最好的一面:
ICommand<object>
的实现,这可以让您在某些不知道要提供的泛型参数的情况下调用GetValue
并返回object
根本不需要它。答案 1 :(得分:2)
如果返回类型必须根据子类而不同,那么最好不要在基类中使用此方法。
首先拥有基类型的想法是让你以统一的方式处理所有子类。一个人应该能够写
Command cmd = ... // One of subclasses
<some-type> val = cmd.GetValue();
并将<some-type>
替换为实际类型。但是,在您的情况下,object
和int
除了string
之外没有共同的基本类型,因此使用不同的返回类型变得毫无意义。
您可以将GetValue
实现为通用,如下所示:
abstract class Command {
abstract T GetValue<T>();
...
}
但是这需要调用者将所需类型作为GetValue
的类型参数传递,这将使基类中GetValue
的目的失效。
可能的解决方法:一种让来电者远离了解类型的方法就是访问者 - 建立一个允许Command
&#34;推送&#34;调用者的值,如下所示:
IValueGetter {
void SetInt(int v);
void SetString(string v);
}
abstract class Command {
abstract void GetValue(IValueGetter g);
}
class TalkCommand {
override void GetValue(IValueGetter g) {
g.SetString("hello");
}
}
class BuyCommand {
override void GetValue(IValueGetter g) {
g.SetInt(123);
}
}
现在调用者可以与Command
进行交互,而不知道其GetValue
的类型。产生int
的命令会回调SetInt
,而产生string
的命令会回拨SetString
。
答案 2 :(得分:1)
仅当您的基类frontend
是通用的或您不介意使用Command
。
通用示例
如果您始终使用已知的实例类型,这将是最好的方法,因为您可以使用所需的数据类型而不需要进行转换。
object
对象示例
这是一种非常通用的方法,几乎是WPF对abstract class Command<T>
{
public abstract T GetValue();
}
class TalkCommand : Command<string>
{
public override string GetValue()
{
return "Test";
}
}
class SpendCommand : Command<int>
{
public override int GetValue()
{
return 1234;
}
}
以及DependencyProperties
或IList
等非通用集合的处理方式。
IEnumerable
混合示例
如果您希望能够同时使用它们,则需要一个非泛型基类并从中继承另一个抽象泛型类。
abstract class Command
{
public abstract object GetValue();
}
class TalkCommand : Command
{
public override object GetValue()
{
return "Test";
}
}
class SpendCommand : Command
{
public override object GetValue()
{
return 1234;
}
}