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
。
问题是,当我实现 IBiasSvdPredictor 时,我必须实现 2 对 PredictRating 方法。一个来自 ISvdPredictor
,另一个来自 IBiasSvdPredictor
。我需要做什么才能实现 IBiasSvdPredictor 中的那些内容?
我也尝试过泛型,但无法使用 where
将 BiasSvdPredictor
的 PredictRating
限制为 IBiasSvdModel
指示。我可能做错了所以任何建议可能会有所帮助。我想你明白我想做的事。
编辑:如果有人需要更多上下文,请参阅 https://github.com/gligoran/RecommendationSystem。我正在为我的理学学士论文编写这段代码。
I'm refactoring some code and want to classes a bit higher in the inheritance chain be a bit more strict with their parameters. As I'm not sure I'm explaining this correctly, here's what I've got:
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
uses ISvdModel
:
public interface ISvdModel
{
float[,] UserFeatures { get; set; }
float[,] ArtistFeatures { get; set; }
}
Now I want to implement another variation:
public interface IBiasSvdPredictor : ISvdPredictor
{
float PredictRating(IBiasSvdModel model, string user, string artist);
float PredictRating(IBiasSvdModel model, int userIndex, int artistIndex);
}
Which uses IBiasSvdModel
which derives from ISvdModel
:
public interface IBiasSvdModel : ISvdModel
{
float GlobalAverage { get; set; }
float[] UserBias { get; set; }
float[] ArtistBias { get; set; }
}
IBiasSvdPredictor
will not work with ISvdModel
.
The problem is that when I implement IBiasSvdPredictor
I'd have to implement 2 pairs of PredictRating methods. One from ISvdPredictor
and the other from IBiasSvdPredictor
. What do I need to do to be able to just implement those from IBiasSvdPredictor
?
I've tried generics as well, but couldn't restrict the PredictRating
for BiasSvdPredictor
to IBiasSvdModel
using the where
directive. I may be doing this all wrong so any suggestion might help. I think you get what I'm trying to do.
EDIT: If anyone needs more context see https://github.com/gligoran/RecommendationSystem. I'm writing this code for my thesis for BSc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用泛型和约束。
You could use generics and constraints.
接口
应该有一个方法,PredictRating。我不会有两个具有相同方法来实现的接口。令人困惑。创建一个实现您的
接口
的抽象
类。将 PredictRating 设为虚拟
方法,以便继承者可以根据需要进行重写。您甚至可以对抽象类进行默认实现。一个接口,一个抽象类。 N 个具体类,按照他们认为合适的方式实现 PredictRating。
The
interface
should have one method, PredictRating. I wouldn't have two interfaces that have the same method to implement. Confusing.Create an
abstract
class that implements yourinterface
. Make PredictRating avirtual
method so inheritors can override as they see fit. You could even do a default implementation on the abstract class.One interface, One abstract class. N concrete class that implement PredictRating as they see fit.
您必须实现所有四种方法。它们具有不同的签名,因此被认为是不同的。但是,您可以将一个委托委托给另一个委托,有时使用显式实现会有所帮助。
如果 ISvdModel 实际上不是 IBiasSvdModel,这当然不起作用。
You have to implement all four methods. They have different signatures and thus are considered to be different. However, you can have one delegate to the other, and sometimes using explicit implementation helps with that.
This of course will not work if the ISvdModel is not actually an IBiasSvdModel.
您可以使用显式接口实现来隐藏 ISvdPredictor 中的接口,但您应该全部实现它们或使用一个基本抽象类来处理它们。
You can use explicit interface implementation to hide the ones from
ISvdPredictor
, but you should implement them all or have a base abstract class to handle them.当然可以。你期待什么?
如果您的
IBiasSvdPredictor
必须 在其PredictRating
方法中采用IBiasSvdModel
,则IBiasSvdPredictor
为不是ISvdPredictor
(因为它不能将ISvdModel
作为第一个参数PredictRating
)并从ISvdPredictor
继承IBiasSvdPredictor
是错误的选择。在我看来,您应该简单地将接口分开,而不是继承另一个接口。
Of course you do. What did you expect?
If your
IBiasSvdPredictor
must take aIBiasSvdModel
in itsPredictRating
method, thanIBiasSvdPredictor
is not anISvdPredictor
(because it cannot take aISvdModel
as the first parameter toPredictRating
) and inheritingIBiasSvdPredictor
fromISvdPredictor
is the wrong choice.In my opinion, you should simply keep the interfaces separate and not inherit one from the other.
如果没有完全理解您的对象模型(因此这实际上可能不适用于您的情况),似乎
ISvdModel
不应该成为接口定义的一部分。它看起来更像是一个实施细节,不一定是您试图执行的合同的一部分。对我来说,将ISvdModel
(或IBiasSvdModel
)传递到实现类的构造函数中更有意义,而不是将其作为ISvdPredictor
的一部分界面。那么您根本不需要 2 个单独的接口定义,您只需拥有单个接口的 2 个实现。您甚至可以更进一步;如果
ISvdPredictor
和IBiasSvdPredictor
之间的唯一区别是一个使用ISvdModel
而另一个使用IBiasSvdModel
,则您甚至不需要 2 个实现,只需要一个,并且您可以为每种情况传递正确的ISvdModel
实例。这是一种称为控制反转的设计模式,特别是使用依赖注入,对于在程序中实现更高级别的代码重用非常强大。Without having a full understanding of your object model (so this may not actually apply in your situation), it seems like maybe
ISvdModel
shouldn't be part of the interface definition. It seems more like it's an implementation detail, not necessarily part of the contract you're trying to enforce. To me it makes more sense to passISvdModel
(orIBiasSvdModel
) into the constructor of your implementation class, not have it as part of yourISvdPredictor
interface. Then you wouldn't need 2 separate interface definitions at all, you would just have 2 implementations of the single interface.You might even be able to take it one step further; if the only difference between
ISvdPredictor
andIBiasSvdPredictor
is that one uses aISvdModel
and the other uses aIBiasSvdModel
, you wouldn't even need 2 implementations, just one, and you would pass in the correct instance ofISvdModel
for each situation. This is a design pattern called Inversion of Control, specifically using Dependency Injection, and is very powerful to achieve higher levels of code reuse in your programs.