我知道在使用泛型类时如何实现我的目标。但要理解为什么泛型方法的语法在非泛型类中被允许(被声明为虚拟或抽象),我似乎无法确定。
第一个代码块显示了一个使用泛型类创建抽象方法的简单示例,该方法返回比基类中约束的接口更具体的接口。
public interface ISeries
{
string Name { get; set; }
string Color { get; set; }
}
public interface ITimeSeries<TY> : ISeries
{
double[] XValues { get; set; }
TY[] YValues { get; set; }
}
public interface IPhasorSeries : ISeries
{
double Magnitude { get; }
double Angle { get; }
}
public class PhasorSeries : IPhasorSeries
{
public string Name { get; set; }
public string Color { get; set; }
public double Magnitude { get; set; }
public double Angle { get; set; }
}
public class Series<T> : ITimeSeries<T>
{
public string Name { get; set; }
public string Color { get; set; }
public double[] XValues { get; set; }
public T[] YValues { get; set; }
}
public abstract class Chart<T> where T : ISeries
{
public abstract T GetSeries();
}
public class AnalogChart : Chart<ISeries>
{
public override ISeries GetSeries()
{
return new Series<float>();
}
}
public class PhasorChart : Chart<IPhasorSeries>
{
public override IPhasorSeries GetSeries()
{
return new PhasorSeries();
}
}
现在,如果从Chart类中删除泛型类型但保留泛型方法的ISeries约束,则会出现以下错误。
public abstract class Chart
{
public abstract T GetSeries<T>() where T : ISeries;
}
public class AnalogChart : Chart
{
public override T GetSeries<T>()
{
// ERROR:
// Cannot implicitly convert type Test.Series<float> to 'T'
// Cannot convert expression type Test.Series<float> to return type 'T'
return new Series<float>();
}
}
public class PhasorChart : Chart
{
public override T GetSeries<T>()
{
// ERROR:
// Cannot implicitly convert type Test.PhasorSeries to 'T'
// Cannot convert expression type Test.PhasorSeries to return type 'T'
return new PhasorSeries();
}
}
看来我并不完全理解在非泛型类中实现泛型方法时会发生什么。使用泛型类时 - 存在多个类定义。当你只有一个通用方法时,它意味着什么?实际上有多种方法吗?或者以某种方式调用相同的方法?
如果抽象和虚拟关键字基本上不支持这种情况,我希望在创建抽象泛型方法时会出错。如果你不能在这里使用语法来避免在其他代码中进行转换,那么如何正确使用抽象泛型方法呢? (我甚至无法将T转换为ISeries--看起来约束在子类中丢失,好像它不知道T必须是一个ISeries)
请注意,此处问题的目的是了解不解决此问题的方法或提出不同的“解决方案”。
答案 0 :(得分:0)
当您的返回类型为T
时,无论T
是什么,您都必须返回T
。您不能返回具有硬编码类型的对象,并希望它是T。
假设您执行以下代码
Series<int> intSeries = angloChart.GetSeries<Series<int>>();
根据GetSeries
的签名,这将是有效的代码,但是,如果可比,您编写的方法会将Series<float>
放入Series<int>
类型的变量中这就是为什么{在返回return new Series<float>();
答案 1 :(得分:0)
当您使用泛型方法时,这意味着您不知道该def user_logged_in_handler(sender,request,user, **kwargs):
UserSession.objects.get_or_create(
user= user,
session_id= request.session.session_key
)
user_logged_in.connect(user_logged_in_handler, sender=CustomUser)
参数的具体类型。
那你如何判断它是T
?
是什么阻止我像这样调用这个方法:
Series<float>
这会导致出现错误,因为在内部您尝试返回var ac = new AnalogChart();
Series<int> series = ac.GetSeries<Series<int>>();
您对泛型类的初步尝试似乎是一种更好的方法。
顺便说一下,你可以“欺骗”编译器让它通过,但这不是一个好主意,除非你绝对确定这将是Series<float>
的类型(即使那时我也会选择不同的策略):
T
答案 2 :(得分:-2)
为了达到预期的效果,我意识到我可以使用显式的接口实现,并避免一起使用泛型。
public interface IChart
{
ISeries GetSeries();
}
public abtract class Chart : IChart
{
public virtual ISeries GetSeries()
{
throw new NotImplementedException();
}
}
public class AnalogChart : Chart, IChart
{
public new ITimeSeries<float> GetSeries()
{
return new Series<float>();
}
ISeries IChart.GetSeries()
{
return GetSeries();
}
}
public class PhasorChart : Chart, IChart
{
public new IPhasorSeries GetSeries()
{
return new PhasorSeries();
}
ISeries IChart.GetSeries()
{
return GetSeries();
}
}
如果您有Chart或IChart变量,则允许获取ISeries,但如果您具有更具体的类型,则允许检索更具体的接口。不幸的是,看起来我不能覆盖抽象,同时使它成为新的,所以我在使用抛出的抽象类中使用虚方法。
我想使用相同的方法名称,虽然我也可以创建&#39; GetPhasorSeries&#39;,&#39; GetTimeSeries&#39;相反的方法,但我真的想挖掘并实现这个特定的结果。
我试图以一种他们没有设计的方式来修饰泛型。 虽然我仍然不确定为什么你会创建一个抽象或虚拟的通用方法。我仍然欢迎任何关于什么模式使用这个结构的想法(考虑到这个问题的所有上下文) )。