[英]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.