C# 接口实现关系只是“Can-Do”关系 关系?

发布于 2024-07-08 22:15:59 字数 341 浏览 8 评论 0原文

今天有人告诉我,C# 中的接口实现只是“Can-Do”关系,而不是“Is-A”关系。 这与我长期以来所相信的LSP(里氏替换原理)相冲突。 我一直认为所有的继承都应该意味着“Is-A”关系。

所以,如果接口实现只是一种“Can-Do”关系。 如果有一个接口“IHuman”和“IEngineer”,并且一个类“Programmer”继承自“IHuman”和“IEngineer”怎么办? “我工程师”? 当然,“程序员”是“IHuman”和“IEngineer”。

如果这只是“Can-Do”关系,是否意味着我们不能期望“程序员”实例行为在被视为 IHuman 和被视为 IEngineer 时可能有所不同?

Today somebody told me that interface implementation in C# is just "Can-Do" relationship, not "Is-A" relationship. This conflicts with my long-time believing in LSP(Liskov Substitution Principle). I always think that all inheritance should means "Is-A" relationship.

So, If interface implementation is just a "Can-Do" relationship. What if there is a interface "IHuman" and "IEngineer", and one class "Programmer" inherits from "IHuman" & "IEngineer"? Surely, a "Programmer" Is A "IHuman" and A "IEngineer".

If it is just "Can-Do" relationship, does it mean we cannot expect the "Programmer" instance behavior may be different between when treated as a IHuman and treated as IEngineer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浪荡不羁 2024-07-15 22:16:00

很晚才发现这个问题,但我想插话。C

# 中的接口有 is-a 关系,但不是 is-an-object 关系。 相反,是一种实现。

换句话说,对于实现 IBar 的类 Foo,以下测试:

Foo myFoo = new Foo(); 
return myFoo is IBar;

字面上返回 true。 你也可以说,

IBar bar = myArrayList[3] as IBar;
Foo foo = bar as Foo;

或者,如果一个方法需要 IBar,你可以传递 Foo。

void DoSomething(IBar bar) {
}

static void Main() {
    Foo myFoo = new Foo();
    DoSomething(myFoo);
}

显然,IBar 本身没有实现,因此 can-do 关系也适用。

interface IBar { void happy(); }
class Foo : IBar
{
    void happy()
    {
        Console.Write("OH MAN I AM SO HAPPY!");
    }
}
class Program
{
    static void Main()
    {
        IBar myBar = new Foo();
        myBar.happy();
    }
}

但是,就此而言,对象继承也是如此。 继承类 Bar 的类 Foo 的对象具有 can-do 关系以及 is-a 关系,与接口的方式相同。 只是它的实现是为其预先构建的。

真正的问题是,is-a-what,can-do-what? 继承的类对象是-[父实例]并且可以-[父的行为],而接口的实现是-[接口实现],因此可以-[接口行为]

在大多数使用编程 is-a 关系(例如上面列出的关系)的情况下,仅评估接口,因此继承的类和实现的接口都共享相同的 is-a 和 can-do 品质。

哈特哈,
乔恩

Found this question rather late but I wanted to chime in.

Interfaces in C# have an is-a relationship, but not is-an-object. Rather, is-an-implementation.

In other words, for class Foo that implements IBar, the following test:

Foo myFoo = new Foo(); 
return myFoo is IBar;

literally returns true. You can also say,

IBar bar = myArrayList[3] as IBar;
Foo foo = bar as Foo;

Or, if a method requires an IBar, you can pass a Foo.

void DoSomething(IBar bar) {
}

static void Main() {
    Foo myFoo = new Foo();
    DoSomething(myFoo);
}

Obviously, an IBar has no implementation in itself, so the can-do relationship also applies.

interface IBar { void happy(); }
class Foo : IBar
{
    void happy()
    {
        Console.Write("OH MAN I AM SO HAPPY!");
    }
}
class Program
{
    static void Main()
    {
        IBar myBar = new Foo();
        myBar.happy();
    }
}

But, for that matter, the same is true of object inheritance; an object of class Foo that inherits class Bar has a can-do relationship as well as an is-a relationship, in the same way as the interface does. It's just that its implementation was pre-built for it.

The real question is, is-a-what, can-do-what? An inherited class object is-a-[parent instance] and can-do-[parent's behavior], whereas an implementation of an interface is-an-[interface implementation] and therefore can-do-[the interface behavior].

In most cases where programmatic is-a relationships are used such as those listed above, only the interface is evaluated, so both an inherited class and an implemented interface share the same is-a and can-do qualities.

HTH,
Jon

围归者 2024-07-15 22:16:00

.NET 框架的设计者使用接口来指定“有一个”(或“可以做”)关系,而“是一个”是使用继承来实现的。

其基本原理可以在在类和接口之间进行选择中找到.NET Framework 开发人员指南的部分:

接口定义了实现者必须提供的一组成员的签名。 接口无法为成员提供实现细节。

因此,由于您的“程序员”和“工程师”示例类很可能具有自己的特定功能,因此使用继承来实现它们会更合适。

The designers of the .NET framework use interfaces to designate a "has a" (or "can do") relationship, whereas "is a" is implemented using inheritance.

The rationale for this can be found in the Choosing Between Classes and Interfaces section of the .NET Framework Developer's Guide:

An interface defines the signatures for a set of members that implementers must provide. Interfaces cannot provide implementation details for the members.

So, since your "Programmer" and "Engineer" example classes would most likely come with their own specific functionality, they would be more suitably implementated using inheritance.

壹場煙雨 2024-07-15 22:16:00

实际上,这就是为什么大多数接口都是功能而不是名称,所以你有

IComparable、ITestable、IEnumerable

Human、Animal、Dog 等

无论如何,正如已经提到的,你必须务实,我有一个一般规则我正在编码:永远不要让概念、惯例或标准实践妨碍完成工作,最好是务实而不是学术。

因此,如果您确定界面确实更适合您的设计,那就去吧对于它,不要担心诸如此类的问题。

Actually that's why most of the interface are capabilities and not names so you have

IComparable, ITestable, IEnumerable

and

Human, Animal, Dog, etc

Anyway, as it has been already mentioned you have to be pragmatic, I've got a general rule when I'm coding: never let concepts, conventions or standard practices get on the way of getting the job done, better be pragmatic than academic.

so if you're sure interfaces really fit better your design, go for it, don't worry about question such as this one.

黑白记忆 2024-07-15 22:15:59

根据我的经验,思考“是”和“可以做”的关系并没有多大帮助。 你很快就会遇到问题。 基本上,这是现实世界和面向对象之间的阻抗不匹配。 无论有多少人实际上谈论对现实世界进行建模,您从根本上都需要了解类型之间的关系在您所使用的平台上意味着什么。

有时接口可以用作功能,有时它们可​​以代表更多正常的“is-a”关系。 我不会太在意它——只要确保你了解他们能做什么和不能做什么就可以了。

In my experience it doesn't really help that much to think of "is-a" and "can-do" relationships. You rapidly get into problems. It's an impedance mismatch between the real world and OO, basically. However much people actually talk about modeling the real world, you fundamentally need to understand what the relationships between types mean on the platform you're using.

Sometimes interfaces can be used as capabilities, and sometimes they can represent more of a normal "is-a" relationship. I wouldn't get too hung up about it - just make sure you understand what they can do and what they can't.

看轻我的陪伴 2024-07-15 22:15:59

我倾向于将接口视为行为契约。 IComparable 和 IEnumerable 等接口就是典型的例子。

在您给出的示例中,IHuman 和 IEngineer 并不是真正的行为。

I tend to think of interfaces as a contract of behaviour. Interfaces such as IComparable and IEnumerable are classic examples.

In the example you gave, IHuman and IEngineer are not really behaviours.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文