[英]Inheritance problem in C#
我正在重构一些代码,并希望继承链中的类更高一些,对它们的参数要严格一些。 由于我不确定我是否正确解释了这一点,这就是我所拥有的:
public interface ISvdPredictor
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(ISvdModel model, string user, string artist);
float PredictRating(ISvdModel model, int userIndex, int artistIndex);
}
ISvdPredictor
使用ISvdModel
:
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
现在我想实现另一种变体:
public interface IBiasSvdPredictor : ISvdPredictor
{
float PredictRating(IBiasSvdModel model, string user, string artist);
float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex);
}
它采用IBiasSvdModel
从派生ISvdModel
:
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
IBiasSvdPredictor
不能与ISvdModel
一起ISvdModel
。
问题是,当我实现IBiasSvdPredictor
我必须实现2对PredictRating方法。 一个来自ISvdPredictor
,另一个来自IBiasSvdPredictor
。 我需要做什么才能实现IBiasSvdPredictor
那些?
我试着仿制药为好,但不能限制PredictRating
为BiasSvdPredictor
到IBiasSvdModel
使用where
指令。 我可能做错了所以任何建议都可能有所帮助。 我想你得到了我想做的事。
编辑:如果有人需要更多上下文,请参阅https://github.com/gligoran/RecommendationSystem 。 我正在为BSc的论文编写这段代码。
您可以使用泛型和约束。
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
public interface ISvdPredictor<in TSvdModel>
where TSvdModel : ISvdModel // Require that TSvdModel implements ISvdModel
{
List<string> Users { get; set; }
List<string> Artists { get; set; }
float PredictRating(TSvdModel model, string user, string artist);
float PredictRating(TSvdModel model, int userIndex, int artistIndex);
}
// I would actually avoid declaring this interface. Rather, see comment on the class.
public interface IBiasSvdPredictor : ISvdPredictor<IBiasSvdModel> { }
class BiasSvdPredictor : IBiasSvdPredictor // Preferred : ISvdPredictor<IBiasSvdModel>
{
// ...
public float PredictRating(IBiasSvdModel model, string user, string artist) { }
public float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex) { }
}
interface
应该有一个方法,PredictRating。 我不会有两个具有相同方法的接口。 混乱。
创建一个实现interface
的abstract
类。 使PredictRating成为一个virtual
方法,以便继承者可以根据需要覆盖它们。 您甚至可以在抽象类上执行默认实现。
一个接口,一个抽象类。 N具体实现PredictRating的具体类。
public interface Demo
{
int PredictRating(int param1);
}
public abstract class AbstractDemo : Demo
{
public virtual int PredictRating(int param1)
{
return param1 + 1;
}
}
public class ClassDemo1 : AbstractDemo
{
//This guy uses AbstractDemo Predict Rating
public override int PredictRating(int param1)
{
return base.PredictRating(param1);
}
}
public class ClassDemo2 : AbstractDemo
{
//This guy overrides the predict rating behavior
public override int PredictRating(int param1)
{
return param1 + 2;
}
}
您必须实现所有四种方法。 它们具有不同的签名,因此被认为是不同的。 但是,您可以将一个委托给另一个委托,有时使用显式实现有助于此。
public class Foo : IBiasSvdPredictor {
public float PredictRating(IBiasSvdModel, string user, string artist) { .... }
// this is an expicit implementation of ISvdPredictor's method. You satisfy
// the interface, but this method is not a public part of the class. You have to
// cast the object to ISvdPredictor in order to use this method.
float ISvdPredictor.PredictRating(ISvdModel model, string user, string artist) {
this.PredictRating((IBiasSvdModel)model, user, artist);
}
}
如果ISvdModel实际上不是IBiasSvdModel,这当然不起作用。
您可以使用显式接口实现来隐藏ISvdPredictor
,但您应该全部实现它们或者有一个基本的抽象类来处理它们。
我必须实现2对PredictRating方法。
你当然可以。 你有什么期望?
如果您IBiasSvdPredictor
必须采取IBiasSvdModel
在其PredictRating
方法,比IBiasSvdPredictor
不是 ISvdPredictor
(因为它不能采取ISvdModel
作为第一个参数来PredictRating
)和继承IBiasSvdPredictor
从ISvdPredictor
是错误的选择。
在我看来,你应该简单地保持接口分离,而不是从另一个继承接口。
如果没有完全理解你的对象模型(所以这可能不适用于你的情况),似乎ISvdModel
不应该是接口定义的一部分。 它似乎更像是一个实现细节,不一定是您试图强制执行的合同的一部分。 对我来说,将ISvdModel
(或IBiasSvdModel
)传递给实现类的构造函数更有意义,而不是将它作为ISvdPredictor
接口的一部分。 那么你根本不需要2个独立的接口定义,你只需要2个单一接口的实现。
你甚至可以更进一步; 如果ISvdPredictor
和IBiasSvdPredictor
之间的唯一区别是一个使用ISvdModel
而另一个使用IBiasSvdModel
,您甚至不需要2个实现,只需要一个,并且您将为每种情况传入正确的ISvdModel
实例。 这是一种名为Inversion of Control的设计模式,特别是使用依赖注入,并且非常强大,可以在程序中实现更高级别的代码重用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.