如何在Dart中模拟受保护的方法?

Set*_*add 16 dart

(在办公室偷听,我们认为其他人会受益)

假设我在库中有一个基类,它提供了一些基本功能,但是它们是由库用户派生的.

例如,我有一个抽象的Greeting类.子类表示特定类型的问候语,如HighFiveGreeting或HugGreeting等等.Greeting为子类提供了一些实用函数,比如sendGreeting().我不希望这些类的用户调用sendGreeting().

那可能吗?对于这种事情,Dart有更好的成语吗?

library greeting;

abstract class Greeting {
   void sendGreeting(GreetingEvent event) { ... }
}
Run Code Online (Sandbox Code Playgroud)
library custom_greeting;
import 'greeting.dart';

class HugGreeting extends Greeting {
   // code here uses sendGreeting()
}
Run Code Online (Sandbox Code Playgroud)
library main;
import 'custom_greeting.dart';

var hug = new HugGreeting();
hug.sendGreeting(...); // should not compile
Run Code Online (Sandbox Code Playgroud)

Nic*_*ich 15

就像说在这里,现在是@protected在注释元包

我很想知道为什么省略BTW语言中的public | private | protected关键字...:'(

  • 使用命名约定来表示私有/公共是有充分理由的。如果您尝试在“动态”上调用私有方法会发生什么?该语言仅在运行时知道“dynamic”的类型,因此调用私有方法必定是运行时错误。按照他们的设置方式,“foo._bar”始终是一个语法错误。这是一种静态访问检查的方式,它是一个有利有弊的功能,而不是缺陷。 (6认同)
  • public|private 关键字被省略,因为所有成员都是公共的,除非它们以下划线开头,在这种情况下它们是私有的,我碰巧喜欢这一点。我同意你的观点,想要一个受保护的关键字而不是注释。 (2认同)
  • @迈克尔P。糟糕的设计:我来这里是为了知道“@protected”是否适用于“_method”或仅适用于“method”。如果他们只给我们“私有”、“公共”和“受保护”,这种怀疑就不会存在。顺便说一句,其他语言(例如 C#)考虑不将访问修饰符用作 public。 (2认同)
  • 他们本可以引入一个新的前缀来指示受保护的修饰符,而不是引入“@protected”属性。 (2认同)
  • 请阅读 https://github.com/dart-lang/sdk/issues/33383,了解关于 dart 中是否有访问修饰符的长时间讨论:) 就我个人而言,我仍然习惯使用下划线。我觉得考虑到 Java 背景,这使得代码有点难以阅读。 (2认同)

hjf*_*yer 9

我相信没有办法做到这一点,但是FWIW,这似乎是一种组合比继承更可取的情况:

class GreetingSender {
    void sendGreeting(GreetingEvent);
}

class HugGreeting {
    GreetingSender _sender;
    HugGreeting(this._sender);

    void hug() {
        // use _sender.sendGreeting()
    }
}
Run Code Online (Sandbox Code Playgroud)

涉及调用在超类中实现的受保护方法的每个设计都有相应的设计,其中超类被通过构造函数注入的接口替换,并且我还没有遇到不改进的情况.


gmo*_*osx 5

我遇到了同样的问题,但有人建议了以下解决方案,这对我有用。我将用一个简短的例子来演示:

library view;

abstract class View {
  factory View({HtmlElement host}) = ViewImpl;

  void enable() {}
}

class ViewImpl implements View {
  HtmlElement host;

  ViewImpl({this.host});

  @override
  void enable() {
    host.classes.remove('disabled');
  }
}
Run Code Online (Sandbox Code Playgroud)

在另一个图书馆:

library button; // notice, this is another library

abstract class Button extends View {
  factory Button({String title, HtmlElement host}) = ButtonImpl; // The magic happens here!
}

class ButtonImpl extends ViewImpl implements Button {
  String title; // voila, a protected property

  ButtonImpl({this.title, HtmlElement host}) : super(host: host);
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它:

final button = new Button(title: "Cancel", host: element);

button.title // => cannot access!
Run Code Online (Sandbox Code Playgroud)

此外,您可以在例如单元测试中访问受保护的字段:

// Instantiate the *Impl class to side-step the protection.
final button = new ButtonImpl(title: "Cancel", host: element);
expect(button.title, equals("Cancel"); // => it works!
Run Code Online (Sandbox Code Playgroud)

简而言之,您将“受保护”方法隐藏在 Impl 类中。您可以在不同的库中自由扩展实现。

希望这可以帮助。