接口实现覆盖等

时间:2010-10-08 01:02:28

标签: c# interface polymorphism override

这是我最简单的问题形式:

IApple除其他外还要求财产Flavor IToffeeApple还需要属性Flavor

问题是,我希望IToffeeApple实现IApple(公共接口IToffeeApple:IApple),但它们都具有相同的属性要求。如果出于一个目的,我需要一个糖果集合(仅限IToffeeApple),其中IToffeeApple也可以被识别为IApple,这就成了一个问题。

在我的界面中使用“new”关键字是否可以,以便任何实施者都有2个Flavor属性?

我解释得不好吗? :\

编辑:我有。实际的上下文是几何:

  • ILine需要一个起点和终点IPoint。
  • ICurve需要一个起点和终点IControlPoint。

ICurve只是ILine之上的额外功能,但它意味着我想将Start和End作为IControlPoint而不是IPoint返回,所以我要么实现两者,要么返回IControPoint和开始和结束的IPoint,或者我只是忽略IPoint / ILine并将DRY抛出窗口。

4 个答案:

答案 0 :(得分:3)

尝试以下方面的内容:

interface IFlavor;
interface ISweets: IFlavor;
interface IApple: IFlavor;
interface IToffeeApple: IApple, ISweets;

IEnumerable<ISweets>可以保留IToffeeApple,但不能保存IApple。

当似乎需要'替换'继承的继承属性时,我通常会寻找两件事之一。要么继承是强制的(汽车和苹果都有颜色,但通常不被认为是多态的),或者继承比初看起来更深。

如果我足够了解这个例子,那么更深的继承就足够了。


为了适应你的新例子:

public interface IPoint
{}

public interface IControlPoint : IPoint
{
    // added functionality of IControlPoint
}

public interface ILine<TPoint>
    where TPoint : IPoint
{
    TPoint Start { get; set; }
    TPoint End { get; set; }
}

public interface ICurve<TPoint> : ILine<TPoint>
    where TPoint : IPoint
{
    // added functionality of ICurve
}

我假设IControlPoint实现IPoint,但这似乎是合理的。

基本上,泛型需要ICurve需要IControlPoint才能使用,而ILine则需要IPoint

答案 1 :(得分:3)

这是David Culp答案的详细阐述。这很长,所以我不会发表评论。

虽然通用接口IList<TPoint>看起来是一个很好的解决方案,但我建议进一步详细说明语义。此外,建议考虑引入某些界面的通用和非通用版本(例如IEnumerableIEnumerable<T>)。

在您的澄清示例中,您应该引入一个术语来描述具有起点和终点的有限实体。通常,曲线不是直线而是直线是曲线。但是,由于曲线使用ControlPoint来描述其开始和结束,而线条使用普通Point代替,在您的特定情况下,线不是曲线。相反,线条和曲线都类似于形状

// this interface will denote any shape that has a starting and ending point
public interface IShape
{
    IPoint Start { get; set; }
    IPoint End { get; set; }
}

// this interface will allow for specialization of staring end ending points' type
public interface IShape<TPoint> : IShape
{
    // note 'new' will be required here most probably, I didn't compile it
    TPoint Start { get; set; }
    TPoint End { get; set; }
}

// a line will be a shape descibed by a pair of points; for the sake of 
public interface ILine : IShape<Point> { }

// a curve will be a shape described by a pair of control points
public interface ICurve : IShape<ControlPoint> { }

然后,ILineICurve的实际实现可以使用来自非通用Start接口的EndIShape属性的显式实现。这将有利于对分隔点进行强类型访问,同时保留与普通IShape s一样使用它们的能力。

 public class Curve : ICurve 
 {
     public ControlPoint Start { get; set; }
     public ControlPoint End { get; set; }
     IShape.Start 
     {
         get { return Start; }
         set 
         {
              if (!(value is ControlPoint)) ... some error handling ...; 
              Start = (ControlPoint)value; 
         }
     }
     IShape.End { ... similarly as IShape.Start ... }
 }

 public class Line : ILine { ... similarly as Curve ... }

请注意,就上面显示的可能错误情况而言,改进可能是将IShape属性仅限于getter。或者,将value传递到StartEnd的强类型版本的setter可以将某个点转换为控制点。当然,正确的解决方案是针对特定领域的。

答案 2 :(得分:1)

不,您不需要new关键字从另一个接口的接口继承属性:

public interface IApple
{
    Flavor Flavor { get; }
}

public interface IToffeeApple : IApple
{
    ICollection<Sweet> Sweets { get; }
}

public class MyToffeeApple : IToffeeApple
{
    public Flavor Flavor { get { return Flavors.ToffeeFlavor; } }
    public ICollection<Sweet> Sweets { get { return new Sweet[0]; } }
}

工作得很好。如果这不能回答您的问题,请编辑问题以包含解释上述内容不足的详细信息。

答案 3 :(得分:0)

不,因为IToffeeApple只是继承自IApple(它没有实现任何东西,它是一个接口)并且没有冲突;只需保留Flavor属性,以便从IApple继承它。

这不会成为一个只有IToffeeApple的集合的属性,因为那里也不存在任何冲突的情况。

如果IToffeeApple同时实现了某些东西,或者其他类型的东西都有不同的类型,或者味道具有不同含义的IQuark,那么它真的会成为一个问题。在这种情况下,实现它们的类应该明确地实现一个或两个属性。