How to emulate protected methods in Dart?

(heard in the office and we thought that others would win)

Suppose I have a base class in a library that provides some basic functions, but which is supposed to be received from a library user.

For example, I have an abstract welcome class. Subclasses are special types of greetings, such as HighFiveGreeting or HugGreeting, or something else. Greeting provides some utility functions for subclasses, such as sendGreeting() . I do not want users of these classes to call sendGreeting() .

Is it possible? Is there a better idiom in Darth for this kind of thing?

 library greeting; abstract class Greeting { void sendGreeting(GreetingEvent event) { ... } } 

 library custom_greeting; import 'greeting.dart'; class HugGreeting extends Greeting { // code here uses sendGreeting() } 

 library main; import 'custom_greeting.dart'; var hug = new HugGreeting(); hug.sendGreeting(...); // should not compile 

+5
source share
6 answers

I believe there is no way to do this, but FWIW, it seems like a situation where composition is preferable to inheritance:

 class GreetingSender { void sendGreeting(GreetingEvent); } class HugGreeting { GreetingSender _sender; HugGreeting(this._sender); void hug() { // use _sender.sendGreeting() } } 

Each construct that involves invoking the protected method implemented in the superclass has a corresponding design in which the superclass is replaced by the interface introduced through the constructor, and I have yet to come across a scenario in which this does not improve the situation.

+6
source

I had the same problem, but someone suggested the following solution that works for me. I will demonstrate with a brief example:

 library view; abstract class View { factory View({HtmlElement host}) = ViewImpl; void activate() { } } abstract class ViewImpl implements View { ViewImpl({this.host}); @override void enable() { host.classes.remove('disabled'); } } 

In another library:

 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); } 

You can use it as follows:

 final button = new Button(title: "Cancel", host: element); button.title // => cannot access! 

In addition, you can access a protected field, for example. a unit test:

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

In short, you are hiding your "protected" methods in Impl classes. You can freely expand the implementation in different libraries.

Hope this helps.

+3
source

As stated here , there is now an @protected annotation in the meta package

I would like to know the reasons to omit public | closed | protected keywords from BTW ...: '(

+2
source

You can do something similar by using the library as a privacy boundary, for example:

 library greetings; abstract class Greeting { void _sendGreeting(String greeting) => print(greeting); } class HugGreeting extends Greeting { void sendHug() => _sendGreeting("Hug"); } 

And in your main file:

 import 'greetings.dart'; HugGreeting hug = new HugGreeting(); hug.sendHug(); 

Thus, only classes that extend from Greeting and reside in the same library can access the low-level _sendGreeting() method.

+1
source

This restricts callers to subclasses and everything that has access to private members of these subclasses.

** greeting library

 class GreetingEvent { final message; GreetingEvent(this.message); toString() => message; } abstract class Greeting { // The sub class has to pass a method to the super constructor // which allows to set a private field in the sub class. Greeting(Function setProtected) { // passes "this" so the passed static method has an instance // context setProtected(this, new GreetingProtected(this)); } // protected void _sendGreeting(GreetingEvent event) { print(event); } } // This class provides access to protected members of Greeting // by just forwarding calls class GreetingProtected { // protected final _greeting; GreetingProtected(this._greeting); void sendGreeting(GreetingEvent event) => _greeting._sendGreeting(event); } 

** custom_greeting library

 library custom_greeting; import 'greeting.dart'; class HugGreeting extends Greeting { // the reference to the GreetingProtected _protected; // pass the method to the super constructor which can // assign the protected-forwarder HugGreeting() : super(_setProtected); // Method passed to the super constructor to pass // the protected-forwarder // Has to be static so it can be passed in the constructors // super call. static _setProtected(HugGreeting greeting, GreetingProtected protected) => greeting._protected = protected; void someMethod() { // code here uses sendGreeting() _protected.sendGreeting(new GreetingEvent('someMethod')); } } 

** main

 library main; import 'custom_greeting.dart'; import 'greeting.dart'; void main() { var hug = new HugGreeting(); //hug.sendGreeting(new GreetingEvent('someMessage')); // should not compile => and doesn't hug.someMethod(); } 
0
source

Why don't you use the almost standard prefix _ to designate a function as private or protected?

I do not think that you should completely block access to a private or protected function. Of course, let the user know that access is not needed, but you should not block it. Only today I found an error in dart-sdk. I could override the failed function and still use the rest of the class, but the class was marked as private ... I needed to copy the class back to my application ... but I was lucky because it did not depend on anything else, but I remember doing something similar in C # for listview, as a result of which I completed the creation of a complete library with a hundred private classes to make a small change.

 library greeting; abstract class Greeting { void _sendGreeting(GreetingEvent event) { ... } } 
 library custom_greeting; import 'greeting.dart'; class HugGreeting extends Greeting { // code here uses _sendGreeting() } 
 library main; import 'custom_greeting.dart'; var hug = new HugGreeting(); hug._sendGreeting(...); // should compile, maybe with a warning... 
-1
source

Source: https://habr.com/ru/post/1212721/


All Articles