繁体   English   中英

C#中的继承问题

[英]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那些?

我试着仿制药为好,但不能限制PredictRatingBiasSvdPredictorIBiasSvdModel使用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。 我不会有两个具有相同方法的接口。 混乱。

创建一个实现interfaceabstract类。 使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 )和继承IBiasSvdPredictorISvdPredictor是错误的选择。

在我看来,你应该简单地保持接口分离,而不是从另一个继承接口。

如果没有完全理解你的对象模型(所以这可能不适用于你的情况),似乎ISvdModel不应该是接口定义的一部分。 它似乎更像是一个实现细节,不一定是您试图强制执行的合同的一部分。 对我来说,将ISvdModel (或IBiasSvdModel )传递给实现类的构造函数更有意义,而不是将它作为ISvdPredictor接口的一部分。 那么你根本不需要2个独立的接口定义,你只需要2个单一接口的实现。

你甚至可以更进一步; 如果ISvdPredictorIBiasSvdPredictor之间的唯一区别是一个使用ISvdModel而另一个使用IBiasSvdModel ,您甚至不需要2个实现,只需要一个,并且您将为每种情况传入正确的ISvdModel实例。 这是一种名为Inversion of Control的设计模式,特别是使用依赖注入,并且非常强大,可以在程序中实现更高级别的代码重用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM