【问题标题】:Interface should not have properties?接口不应该有属性吗?
【发布时间】:2010-11-01 15:00:07
【问题描述】:

我的办公室同事今天告诉我,在接口中使用属性是不好的做法。他在一些我找不到的 MSDN 文章中指出了这一点(好吧,我在 google 上尝试了几次,可能使用了错误的关键词)。他还告诉我只有方法应该在接口中。 现在,我知道这不是严格的规则,因为显然在 .net 中您可以在接口中进行属性签名并进行编译。

但这真的是一种不好的做法/设计/oop吗?为什么?

指出正确的文献或网络资源也会有所帮助。

谢谢

【问题讨论】:

    标签: .net design-patterns oop


    【解决方案1】:

    我从来没有遇到过任何人提出这种说法,我也看不出有什么好的理由。 .NET 框架充满了带有属性的接口。

    【讨论】:

      【解决方案2】:

      我也将在这里添加我的声音 - 我从未遇到过此建议。属性实际上是一对 get/set 方法。

      与其他所有设计决策一样。如果它真的有道理;如果它适用于正在设计的系统,如果它不会导致维护问题,如果它不会导致性能问题,那么你应该没有理由不能这样做。

      【讨论】:

        【解决方案3】:

        有一个广为人知的术语“代码异味”。我建议引入“程序员气味”的概念——如果有人坚持某些规则,但无法解释为什么——那就是一种气味。您的同事应该能够解释为什么界面中的属性不好。如果他不能——即使他所指的文章是正确的,他也可能是错的。

        那篇文章可能是在讨论某些特定类型的接口,可能与 COM 和互操作性或其他什么有关。或者他可能只是弄错了。理解规则并能够解释它们是使用规则的重要部分。

        【讨论】:

          【解决方案4】:

          接口是类实现的契约,我认为没有理由将属性排除在此类契约之外。此外,属性是 .NET 固有的。

          例如:ICollection<T> 同时拥有CountIsReadOnly

          【讨论】:

            【解决方案5】:

            本身从未见过这样的事情,但前段时间有人谈论不要在跨平台接口定义中使用属性,因为有许多平台不支持属性,但几乎所有东西都支持方法。

            【讨论】:

            • 你所说的“跨平台界面”是什么意思?
            • 不是 BCL“公共接口 foo”意义上的接口。而是接口规范。 W3C 的文档对象模型规范就是一个很好的例子。
            【解决方案6】:

            我能想到的唯一方法是,当您为托管在不同机器或应用程序域上的服务(例如 WCF、WebServices、Remoting)定义接口时,为什么属性对接口不利。

            Cause 属性意味着它们很快(也就是获取和设置值),这对于服务来说是不正确的,因为网络和序列化活动。在服务接口中获取或设置值的显式方法意味着完成操作可能需要一些时间。

            【讨论】:

              【解决方案7】:

              我想不出任何文件来支持这个前提。此外,我可以想到 BCL 中的许多例子,它们的作用完全相反。看看几乎所有的集合接口,你就会看到属性。

              【讨论】:

                【解决方案8】:

                实际上,一个属性由两个功能组成:一个用于获取值,另一个用于设置值。尽管属性是 C# 的一流“特性”,但这仍然是正确的。

                为什么不允许在接口中使用属性?

                【讨论】:

                  【解决方案9】:

                  我认为没有理由不将属性作为界面的一部分。您将如何实现对数据成员的访问?获取方法和设置方法而不是属性。那会很丑陋,所以 1990 年代。

                  【讨论】:

                    【解决方案10】:

                    我可以看到属性与方法的唯一缺点是,虽然有一个带有 get 方法的接口、一个带有 set 方法的接口和一个结合了这两者的接口没有问题(这种情况将允许最大的灵活性具有协变和逆变),属性不能很好地结合。我不确定为什么不能简单地将读写属性视为与读取属性和写入属性相同,但事实并非如此。如果接口支持同名的只读属性和只写属性,则任何通过组合接口访问属性的尝试都将基于声明的歧义而失败。

                    【讨论】:

                      【解决方案11】:

                      这是一个糟糕的设计,因为您污染了实现的变量空间,该变量空间用于使用用作类合同一部分的变量来存储状态。

                      【讨论】:

                      • 你能解释一下你在这里说了什么吗?我知道已经过去了 3 年,但我对这个问题很感兴趣,而且我认为使用属性没有问题,但我希望反对的论点能够正确决定。
                      【解决方案12】:

                      IEnumerator 是需要属性作为接口成员的场景的完美示例。如果不强制实施者这样做,您将如何存储当前元素?

                      【讨论】:

                        【解决方案13】:

                        我看到这是一个 .Net 问题;但是,这种想法可能来自 Java 背景。它让我想起了 Effective Java 中的第 22 条:仅使用接口来定义类型

                        此建议并未禁止接口中的所有属性。它专门针对包含 only 属性的接口。

                        当一个类实现一个接口时,该接口作为一个type,可以用来引用该类的实例。因此,一个类实现了一个接口应该说明客户端可以对类的实例做什么。为任何其他目的定义接口是不合适的。

                        未能通过此测试的一种接口是所谓的常量接口。这样的接口不包含任何方法;它仅由静态最终字段组成...

                        常量接口模式是对接口的不良使用。一个类在内部使用一些常量是一个实现细节。实现一个常量接口会导致这个实现细节泄漏到类的导出 API 中……它代表了一个承诺:如果在未来的版本中修改了类,使其不再需要使用常量,它仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的命名空间都会被接口中的常量污染。

                        当然,Java 本身(可能还有 C#)包含这些常量接口的示例。这本书也解决了这个问题。

                        Java平台库中有几个常量接口……这些接口应该被视为异常,不应该被模仿。

                        我同意以前的答案,我从未见过建议避免同时包含属性和方法的接口。

                        【讨论】:

                          猜你喜欢
                          • 2011-02-14
                          • 2012-05-26
                          • 2011-01-25
                          • 2014-10-18
                          • 2015-11-12
                          • 2019-09-05
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多