[英]Dynamic return type that depends on subclass in C#?
我想用抽象的getter GetValue
声明一个基类Command
。 然后,我将其子类TalkCommand
和SpendCommand
。
这两个类都必须实现GetValue
,但是,我想让TalkCommand
返回GetValue
string
类型( TalkCommand
什么?),我想让SpendCommand
返回int
类型。 (要花多少钱?)
我不知道如何在Command
基类中编写此代码。 这种设计在C#中可行吗?
除了曼弗雷德(Manfred)的答案,我想给你一个提示,进一步说明。
虽然泛型为您提供了定义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();
与其将命令定义为抽象类,不如将其定义为具有协方差的接口:
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
。 如果返回类型必须根据子类而有所不同,则最好不要在基类中使用此方法。
首先具有基本类型的想法是让您以统一的方式处理所有子类。 一个应该能够写
Command cmd = ... // One of subclasses
<some-type> val = cmd.GetValue();
并将<some-type>
替换为实际类型。 但是,在您的情况下,除了int
和string
object
以外,没有其他通用的基本类型,因此拥有不同的返回类型变得毫无意义。
您可以将GetValue
实现为通用,如下所示:
abstract class Command {
abstract T GetValue<T>();
...
}
但这要求调用者将所需的类型作为GetValue
类型参数传递,这将使在基类中具有GetValue
的目的GetValue
。
可能的解决方法:一种使调用者不知道类型的方法是访客-创建一个接口,使Command
将值“推”到调用者中,如下所示:
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);
}
}
现在,调用者可以在不知道其GetValue
类型的情况下与Command
进行交互。 产生int
命令将回调SetInt
,而产生string
命令将调用SetString
。
仅当您的基类Command
是通用的,或者您不介意使用object
。
通用示例
如果您始终使用已知的实例类型,那么这将是最好的方法,因为您可以无需转换就可以使用所需的数据类型。
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;
}
}
对象实例
这是一种非常通用的方法,几乎是WPF对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;
}
}
混合范例
如果要同时使用两者,则需要一个非泛型基类并从中继承另一个抽象泛型类。
abstract class Command
{
public abstract object GetValue();
}
abstract class Command<T> : Command
{
public T GetTypedValue()
{
return (T)GetValue();
}
}
class TalkCommand : Command<string>
{
public override object GetValue()
{
return "Test";
}
}
class SpendCommand : Command<int>
{
public override object GetValue()
{
return 1234;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.