C# 继承接口,实现部分方法,让派生类实现其余方法

C# 继承接口,实现部分方法,让派生类实现其余方法,c#,class,inheritance,interface,C#,Class,Inheritance,Interface,定义以下C#接口: public interface IShape { int NumberOfLineSegments {get;} int Area {get;} } public abstract class Rectangle : IShape { public int NumberOfLineSegments { get { return 4; } } public abstract float Area { get; } } 接下来,我想定义几个矩

定义以下C#接口:

public interface IShape
{
    int NumberOfLineSegments {get;}
    int Area {get;}
}
public abstract class Rectangle : IShape {
    public int NumberOfLineSegments { get { return 4; } }
    public abstract float Area { get; }
}
接下来,我想定义几个矩形类:梯形、正方形等。所有这些类的Area()属性都不同,但NumberOfLineSegments()总是返回4。因此,我想要一个名为Rectangle(或IRectangle)的“临时”类或接口,它看起来像:

public Rectangle : IShape
{
    public int NumberOfLineSegments{get{return 4;}}
}
我希望矩形仅实现NumberOfLineSegment(),并将其留给其派生类来实现其余部分:

public Square : Rectangle 
{
    public int Area() {get{return length*height;}
}
但是,由于IShape是一个接口,Rectangle类还必须实现Area(),它不知道如何实现。。 因此,我似乎被卡住了,要么为矩形定义一个'dummy'Area()方法,要么根本不使用继承


有没有办法避免这种情况?我通过c#和StackOverflow广泛阅读了里克特的clr。提前谢谢

Rectangle
类应该是
abstract
并将
Area()
方法定义为abstract

public interface IShape
{
    int NumberOfLineSegments {get;}
    float Area{get;}
}

public abstract class RectangleBase : IShape
{
    public int NumberOfLineSegments { get { return 4; } }

    public abstract float Area { get; }
}

public sealed class Square : RectangleBase
{
    public override fload Area() { get { return length*height; }
}
public abstract float Area{get;}
如果需要矩形实例:

public sealed class Rectangle : ReectangleBase
{
    public int NumberOfLineSegments { get { return 4; } }

    public float Area { get { throw new NotImplementedException(); } }
}

将方法定义为抽象

public interface IShape
{
    int NumberOfLineSegments {get;}
    float Area{get;}
}

public abstract class RectangleBase : IShape
{
    public int NumberOfLineSegments { get { return 4; } }

    public abstract float Area { get; }
}

public sealed class Square : RectangleBase
{
    public override fload Area() { get { return length*height; }
}
public abstract float Area{get;}

使用实现接口的抽象类:

public interface IShape
{
    int NumberOfLineSegments {get;}
    int Area {get;}
}
public abstract class Rectangle : IShape {
    public int NumberOfLineSegments { get { return 4; } }
    public abstract float Area { get; }
}

然后,您的特定矩形类只需从矩形抽象类继承即可。

这样可以吗?强制在派生类中实现

public abstract class Rectangle : IShape
{
    NumberOfLineSegments{get{return 4;}}
    abstract float Area { get; }
}
有两种选择

  • 将实现设为虚拟且为空(或抛出一个
    NotImplementedException
    ),这样在派生之前,它默认不执行任何操作
  • 使基类抽象,并为要强制执行链的接口方法创建抽象签名
  • 数字2更可取,因为它强制派生类实现该方法,而在数字1中,派生类不强制重写基虚方法

    抽象方法可以成功地满足接口定义,因为编译器知道抽象类本身不能实例化,任何派生类都必须实现抽象方法

    这就是说,如果存在对特定类型没有意义的接口成员,它通常是分解接口的指标:

    public interface IShape : ICalculateArea, IHaveLineSegments
    {
    }
    
    public interface ICalculateArea
    {
        float Area { get; }
    }
    
    public interface IHaveLineSegments
    {
        int NumberOfLineSegments { get; }
    }
    
    class Rectangle : IHaveLineSegments
    {
        public int NumberOfLineSegments { get; private set; }
    }
    
    class Square : Rectangle, IShape
    {
        public float Area { get; private set; }
    }
    

    就我个人而言,我更喜欢@sll的解决方案(以及其他基本相同的解决方案),但要记录在案,还有一种方法:

    public interface IShape
    {
        int NumberOfLineSegments {get;}
        float Area{get;}
    }
    
    public class Rectangle
    {
        public int NumberOfLineSegments { get { return 4; } }
    }
    
    public sealed class Square : Rectangle, IShape
    {
        public float Area() { get { return length*height; }
    }
    
    通过这种方式,您可以节省
    抽象
    类的时间,同时需要定义一个严格的超类(因此您将无法为
    正方形
    使用不同的超类)


    请注意,尽管
    Rectangle
    没有实现
    IShape

    顺便说一句,但如果你计划自己的职业或未来与编程/软件开发相关,我建议你阅读OOP的基础知识,最好像其他人建议的那样将类
    抽象化。但是对于命名,作为几何量,我认为你应该考虑调用你的类<代码>四边形< /代码>,这就是一般的四边多边形(或四边形)。不是一个以英语为母语的人。顺便说一句,@sll可能,尽管我认为这是自以为是的。可以在派生类中派生服务的契约,并且仍然保持良好的代码和契约的含义——毕竟,这样做的人是在试图实现DRY原则。好点。不过,我建议你把这个建议放在你自己的答案上,如果你觉得值得把它放在我的身上。当决定是否分裂接口时,我认为重要的是要考虑代码是否有时会引用某个不能执行特定功能的东西是有意义的,但在其他时候,当引用碰巧标识了一个可以执行该功能的实例时,请使用该功能。当这种用法有用时,持有对其成员不能在所有实例上使用的接口类型的引用可能比持有对不太特定的接口类型的引用并在需要其功能时将其强制转换为特定类型更有帮助,就我个人而言,我倾向于明确地将类标记为基类,因此所有设计为基类的类都应该标记为
    abstract
    ,这样您就不会发现自己在有人实例化类时遇到这种情况,如果有人继承了它,将来扩展这样一个类或进行重构都会很混乱,这将是一个错误mess@sll:是的,标记意图是个好主意;我的想法是提供一个不同的实现(我想不是每个人都希望我的代码在第一时间编译)。所有其他答案似乎都在同一条轨道上:interface=>abstractproto-implementation=>actual-implementation,如果接口更大,则需要大量proto中的样板文件。用与你相同的想法再回答一个问题没有多大意义,对吗?:)