han*_*asm 22 .net c# oop polymorphism interface
我遇到了与多态类型(甚至多态接口)交互的接口概念的问题.我正在开发C#并希望接近这个定义的答案,尽管我认为这仍然为每个人提供了足够的空间来提出答案.
举个例子,假设你想制作一个绘制东西的程序.您可以为Paints定义一个接口,并为绘制的主体定义一个接口.此外,您还可以使用更具体的方式绘制一些主题.
interface IPainter {
void paint(IPaintable paintable);
}
interface IPaintable {
void ApplyBaseLayer(Color c);
}
interface IDecalPaintable : IPaintable {
void ApplyDecal(HatchBrush b);
}
Run Code Online (Sandbox Code Playgroud)
我可以想象制作一个类似于以下的画家:
class AwesomeDecalPainter : IPainter
{
public void paint(IPaintable paintable) {
IDecalPaintable decalPaintable = (IDecalPaintable)paintable;
decalPaintable.ApplyBaseLayer(Color.Red);
decalPaintable.ApplyDecal(new HatchBrush(HatchStyle.Plaid, Color.Green));
}
}
Run Code Online (Sandbox Code Playgroud)
当然,如果paintable没有实现IDecalPaintable,这将抛出.它立即引入了IPainter实现与其操作的IPaintable之间的耦合.但是我也认为说AwesomeDecalPainter不是IPainter是不合理的,因为它的使用仅限于IPaintable域的一个子集.
所以我的问题实际上是四方面的:
ste*_*lin 16
类的接口意味着该类的"用户"的工具.接口是该类的公开演示,它应该向任何考虑使用它的人宣传哪些方法和常量可用并可从外部访问.因此,顾名思义,它始终位于用户和实现它的类之间.
另一方面,抽象类是一种旨在帮助扩展它的类的"实现者"的工具.它是一个基础设施,可以对具体类应该是什么样的实施限制和指导.从类设计的角度来看,抽象类在界面上比界面更重要.在这种情况下,实现者位于抽象类和具体类之间,将后者构建在前者之上.
所以简单地回答你的问题,Interface是一个尊重代码的"契约".当以这种方式使用时,它更适用于多态性的继承.
抽象类,它们定义了一个'类型'.当具体的子类使用抽象类并重新定义方法时,添加新的等等......你会看到多态在行动中.
我知道这篇文章可能会让你更加困惑,在我学习设计模式之前,这对我来说没有意义.通过一些简单的模式,您将更好地理解每个对象的作用以及继承,多态和封装如何共同构建设计简洁的应用程序.
祝好运
接口不仅与多态相兼容 - 它们也是必不可少的.您似乎缺少的部分想法是,如果有一个像IPaintable这样的接口,期望实现它的每个对象都会提供一些默认的绘制方法,通常封装其他方法,以一些有用的方式配置对象.
例如,一个IPaintable接口可能会定义一个paint方法:
void Paint(ICanvas canvas);
请注意,Paint方法没有说明应该绘制什么,也没有说明什么颜色,也没有任何其他内容.各种可绘制的对象会暴露属性来控制这些事物.例如,Polygon方法可能会处理OutlineColor和FillColor属性以及SetVertices()方法.想要绘制大量对象的例程可以接受IEnumerable(Of IPaintable)并简单地在所有对象上调用Paint,而不必知道它们将如何被绘制.通过调用Paint来绘制对象的事实,除了应该绘制它的画布之外没有任何参数,这决不会阻止Paint方法执行各种奇特的渐变填充,纹理映射,光线跟踪或其他图形效果.指挥绘画的代码对这些东西一无所知,但是IPaintable对象本身会保存他们需要的所有信息,因此不需要调用代码来提供它.
问题实际上是你定义了一个模糊的界面,合同是一个更合适的术语.这就像你进入麦当劳并且只是点一个汉堡:
interface Resturant
{
Burger BuyBurger();
}
Run Code Online (Sandbox Code Playgroud)
接受订单的人会在一段时间内看起来有点困惑,但最终他/她将为您提供任何汉堡,因为您没有指定您想要的东西.
这里也是一样的.你真的只想定义一些东西是可以涂漆的吗?如果你问我,就像在寻找麻烦一样.始终尝试使接口尽可能具体.拥有几个小型特定接口总是比一般大型接口更好.
但让我们回到你的例子.在您的情况下,所有类只需要能够绘制一些东西.因此我会添加另一个更具体的界面:
interface IPainter
{
void Paint(IPaintable paintable);
}
interface IDecalPainter : IPainter
{
void Paint(IDecalPaintable paintable);
}
interface IPaintable
{
void ApplyBaseLayer(Color c);
}
interface IDecalPaintable : IPaintable
{
void ApplyDecal(HatchBrush b);
}
class AwesomeDecalPainter : IDecalPainter
{
public void Paint(IPaintable paintable)
{
IDecalPaintable decalPaintable = paintable as IDecalPaintable;
if (decalPaintable != null)
Paint(decalPaintable);
else
paintable.ApplyBaseLayer(Color.Red);
}
public void Paint(IDecalPaintable paintable)
{
paintable.ApplyBaseLayer(Color.Red);
paintable.ApplyDecal(new HatchBrush(HatchStyle.Plaid, Color.Green));
}
}
Run Code Online (Sandbox Code Playgroud)
我建议您阅读有关SOLID原则的内容.
更健全的接口实现
interface IPaintingContext
{
//Should not be object. But my System.Drawing knowledge is limited
object DrawingSurface { get; set; }
}
interface IPaintable
{
void Draw(IPaintingContext context);
}
class AwesomeDecal : IPaintable
{
public void Draw(IPaintingContext paintable)
{
// draw decal
}
}
class ComplexPaintableObject : IPaintable
{
public ComplexPaintableObject(IEnumerable<IPaintable> paintable)
{
// add background, border
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,您可以创建尽可能复杂的绘画项目.他们现在知道他们画的是什么,或者在同一表面上使用了什么样的其他画板.
我正确理解你的问题吗?
我认为你的问题是接口是否可以行使继承的要领?
(即子接口继承父接口)。
1)如果是这样,从语法上来说肯定是这样,为什么不呢?
2)至于实用性,它可能没有什么价值,因为您的子接口本质上并没有重用父接口中的任何内容。