类的设计

最后更新于:2022-04-02 05:55:20

[TOC] Dart是一种“纯粹的”面向对象语言,因为所有对象都是类的实例。但Dart并不要求在类中定义所有代码 - 您可以在过程或函数语言中定义顶级变量,常量和函数。 ## 避免在简单函数可以胜任时定义一个成员的抽象类。 与Java不同,Dart具有一流的功能,闭包和使用它们的轻松语法。如果您只需要回调,只需使用一个函数即可。如果您正在定义一个类,并且它只有一个具有无意义名称的抽象成员,call或者invoke,您很可能只需要一个函数。 ~~~ typedef Predicate = bool Function(E element); ~~~ 以下是反面例子: ~~~ abstract class Predicate { bool test(E element); } ~~~ ## 避免定义仅包含静态成员的类。 在Java和C#中,每个定义都必须在一个类中,所以通常看到“类”只存在于静态成员的位置。其他类用作命名空间 - 一种为一堆成员提供共享前缀以使它们彼此关联或避免名称冲突的方法。 Dart具有顶级函数,变量和常量,因此您不需要一个类来定义某些东西。如果您想要的是命名空间,那么库更适合。库支持导入前缀和显示/隐藏(show/hide)组合器。这些功能强大的工具可让代码的使用者以最适合他们的方式处理名称冲突。 如果函数或变量在逻辑上与类无关,请将其置于顶层。如果您担心名称冲突,请为其指定更精确的名称,或将其移动到可以使用前缀导入的单独库中。 ~~~ DateTime mostRecent(List dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } const _favoriteMammal = 'weasel'; ~~~ 以下是反面例子: ~~~ class DateUtils { static DateTime mostRecent(List dates) { return dates.reduce((a, b) => a.isAfter(b) ? a : b); } } class _Favorites { static const mammal = 'weasel'; } ~~~ 在惯用的Dart中,类定义了各种对象。从未实例化的类型是代码特征。 但是,这不是一个严格的规定。对于常量和类似枚举的类型,将它们组合在一个类中可能是很自然的。 ~~~ class Color { static const red = '#f00'; static const green = '#0f0'; static const blue = '#00f'; static const black = '#000'; static const white = '#fff'; } ~~~ ## 避免扩展了一个不打算进行子类扩展的类。 如果构造函数从生成构造函数更改为工厂构造函数,则调用该构造函数的任何子类构造函数都将中断。此外,如果一个类更改了它调用的自己的方法this,那么可能会破坏覆盖这些方法的子类,并期望在某些点调用它们。 这两个都意味着一个类需要考虑是否要允许子类化。这可以在doc注释中提现,或者通过给类明显的名称来表达IterableBase。如果类的作者不这样做,它的最好假设你应该不扩展类。否则,稍后更改它可能会破坏您的代码。 ## 如果你的类支持扩展请提供文档注释 这是上述规则的必然结果。如果要允许类的子类,请说明。使用类名称后缀Base,或在类的doc注释中提及它。 ## 避免实现一个不打算成为接口的类。 隐式接口是Dart中的一个强大工具,可以避免在从该合同的实现签名中轻易推断出类的合同时重复它。 但实现类的接口是与该类非常紧密的耦合。它实际上意味着对您正在实现的接口的类的任何更改都将破坏您的实现。例如,向类中添加新成员通常是安全,不间断的更改。但是如果你正在实现该类的接口,那么现在你的类有一个静态错误,因为它缺少该新方法的实现。 库维护者需要能够在不破坏用户的情况下发展现有类。如果你把每个类都视为暴露了一个用户可以自由实现的接口,那么改变这些类就变得非常困难了。反过来,这种困难意味着您所依赖的库增长速度较慢,能够适应新的需求。 为了给你的类的作者提供更多的余地,避免实现隐式接口,除了明确要实现的类。否则,您可能会引入作者不想要的耦合,并且可能会在没有意识到的情况下破坏您的代码。 ## 如果你的类支持作为接口使用请提供文档注释。 如果您的类可以用作接口,请在类的doc注释中提及。 ## 避免在并不支持mixing的类中使用mixin 如果将一个构造函数添加到以前没有定义任何类的类中,那么会破坏混合它的任何其他类。这是类中看似无害的变化,并且对mixin的限制并不广为人知。作者可能会添加一个构造函数而不会意识到它会破坏你的类混合它。 与子类化一样,这意味着类需要考虑是否允许将其用作mixin。如果班级没有文档注释或明显的名称IterableMixin,你应该假设你不能在类中使用mix。 ## 如果您的类支持用作mixin,请提供文档注释。 在类的文档注释中提及该类是否可以或必须用作mixin。如果您的类只是作为mixin使用,那么请考虑添加 Mixin到类名的末尾。
';