Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add syntax to support object protected inheritance #3193

Closed
DartBot opened this issue May 23, 2012 · 20 comments
Closed

Add syntax to support object protected inheritance #3193

DartBot opened this issue May 23, 2012 · 20 comments
Assignees
Labels
area-language New language issues should be filed at https://github.com/dart-lang/language

Comments

@DartBot
Copy link

DartBot commented May 23, 2012

This issue was originally filed by le...@google.com


From discussion thread: https://groups.google.com/a/dartlang.org/group/misc/browse_thread/thread/6fd72014c119934d/6bed87932b58b762?lnk=raot#­6bed87932b58b762

Some variant of protected inheritance would be useful, and a protected by object sort of inheritance would likely be better than protected by class, because class based protection leads to any subclass being able to mess with any other subclass in unexpected ways. Because object protected methods could be statically bound, there is no need to require a prefix to identify them, so the concept could be orthogonal to library privacy. Here is a proposed syntax:

class c {
  // This is publicly visible
  var publicFunc() {}

  // This can be accessed by any code in this library
  var _privateFunc() {}

  // This can only be invoked on this
  var this.protectedFunc() {}

  // This can only be invoked on this by code in this library
  var this._privateProtectedFunc() {}
}

@kasperl
Copy link

kasperl commented May 24, 2012

Added Area-Language, Triaged labels.

@gbracha
Copy link
Contributor

gbracha commented May 24, 2012

Set owner to @gbracha.
Added this to the Later milestone.
Added Accepted label.

@DartBot
Copy link
Author

DartBot commented Oct 3, 2012

This comment was originally written by le...@google.com


It occurs to me that this gets more interesting when you consider properties, because you can have different levels of protection on the getter and setter without giving them different names if you use object protection. In C# it is common to declare properties "public int Foo { get; private set; }" as this is what you want 90% of the time; a value that can be read by anyone but can only be set by the class. Dart doesn't have a short syntax like this, but a keyword akin to final on a field that makes it readable by any object but only writeable on this would be just as good for this case, and this covers a very large fraction of the use of properties.

@DartBot
Copy link
Author

DartBot commented Jun 24, 2013

This comment was originally written by off...@mikemitterer.at


The lacking of a way to protect functions from outside usage leads to more public functions and this could not be in the sense of small class interfaces...

The use of Mixins oder the Strategy-Pattern doesn't solve the problem either.

Sample:
abstract class Mixin1 {
  String _objectToString() => "Robin";
}

class JsonTestA implements Mixin1 {
  String getName() => _objectToString();
  
  String _objectToString() => "Batman";
}

class JsonTestB extends JsonTestA with Mixin1 {
  String getName() => _objectToString();
}

testMixins() {
  final Logger logger = new Logger("test.testMixins");
  
  group('Mixins', () {

    test(' -> generate', () {
      final JsonTestA jt = new JsonTestB();

      // True if Mixin1 is in the same library, but if not, the test fails!
      expect(jt.getName(),"Robin");
      });
   });
}

There is no way to define a Template with private functions in a library and keep those function protected or private in subclasses defined in another library.

@DartBot
Copy link
Author

DartBot commented Jan 20, 2014

This comment was originally written by nbil...@gmail.com


I'm sure the Dart engineers have thought about this heavily, but I did want to chime in that there are a growing number of workarounds in the Dart codebase due to lack of the protected namespace.

Examples:
ChangeNotifier observed(), unobserved() -- made public so they are overridable, which doesn't make sense to the consumer of the ChangeNotifier API.

ObservableList _recordChange -- private, requiring any subclass of ObservableList to copy several methods to use that functionality.

I feel that the lack of protected makes the developer choose between either allowing their code to be extensible or keeping their public API clean.

@kevmoo
Copy link
Member

kevmoo commented Jan 20, 2014

I pondered doing this as an annotation. See https://code.google.com/p/dart/issues/detail?id=6119

Zero effect on runtime behavior. It'd basically act like @­deprecated.

The editor/analyzer would show warnings if used outside of the class hierarchy.

We get most of the benefits desired without having to make the type system more complicated.

@DartBot
Copy link
Author

DartBot commented Jan 21, 2014

This comment was originally written by le...@google.com


Kevin, your proposal seems geared toward class-based protection, whereas this bug is related to object-based protection. While class-based protection is the more common form, I'm not aware of any use cases of it that wouldn't fit the object-based model better. The other reason to go with it is because it doesn't rely on the type system to determine visibility, it can be implemented fully in dart, whereas with class-based you'd want a more limited implementation like your annotation proposal.

@kasperl
Copy link

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl
Copy link

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@DartBot
Copy link
Author

DartBot commented Oct 13, 2014

This comment was originally written by le...@google.com


New thread on this: https://groups.google.com/a/dartlang.org/d/topic/misc/cvjjgrwIHbU/discussion

Lasse suggested a name-based approach, and while it's not necessary to go that route it would be very easy to implement that way. So for example, if we make all protected functions prefixed by "**", then all the compiler has to do is 1.) Do not mangle ** names at all, the way it does for _ names, and 2.) Forbid any calls to a __ member of any object other than this. No static analysis necessary.

This variant has the potential feature that it would allow classes to call protected methods defined in subclasses. Or this could be prevented with some straightforward static analysis.

Also, no one will accidentally override a protected method with a public method.

@DartBot
Copy link
Author

DartBot commented Oct 15, 2014

This comment was originally written by le...@google.com


It occurs to me that you could support a combination of 1) object protected and 2) static class protected easily, and they could be used in combination as a way of doing class protected inheritence. It would be a little convoluted, but I don't know that it's a common use case anyway. So for example:

// library A:

class BaseClass {
  void __protectedFunc() {}

  void _callProtectedFunc() => __protectedFunc(); // legal, calling protected func on this.
  // exposes __protectedFunc to all subclasses even when not invoking on this
  static void __callProtectedFunc(BaseClass other) {
    // other.__protectedFunc() // compiler error; protected member functions can only be invoked on this.
    other._callProtectedFunc(); // legal, library private call.
  }
}

// library B:

class SubClass extends BaseClass {
  void doSomethingWith(BaseClass other) {
     __protectedFunc() // legal, invoked on this
    // other.__protectedFunc() // compiler error; protected member functions can only be invoked on this
    // other._callProtectedFunc() // runtime error/compile-time warning; cannot call library private method
    BaseClass.__callProtectedFunc(other) // okay, SubClass inherits from BaseClass
  }
}

class Unrelated {
  void func(BaseClass other) {
    // BaseClass.__callProtectedFunc(other) // compiler error; Unrelated does not inherit from BaseClass.
  }
}

@DartBot
Copy link
Author

DartBot commented Feb 14, 2015

This comment was originally written by @Emasoft


Dart needs protected members. The very useful "protected" keyword is sorely missing. Currently many people are using workarounds to reproduce the protected state. For example here is a method to do it:

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 you write:

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

....and you can use it like this:

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

button.title // => cannot access!

....moreover, you can access the protected field in e.g. 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 hide your 'protected' methods in Impl classes. You can freely extend the implementation in different libraries.

Source: http://stackoverflow.com/a/28513391/959398

Those workarounds are spreading and making the Dart code of many libraries unreadable and messy. Please add the "protected" keyword to the standard Dart syntax specifications.

Thanks.

@DartBot
Copy link
Author

DartBot commented Feb 14, 2015

This comment was originally written by @zoechi


Doesn't need to be a keyword. An annotation @­protected like @­override would be enough. And it wouldn't require a language change at all. The analyzer complaining about violation of protected access and IDE's not listing them in autocompletion when not appropriate would be enough.

@DartBot
Copy link
Author

DartBot commented Feb 14, 2015

This comment was originally written by @Emasoft


Ok, but please do it quickly. Those workarounds are spreading and making the Dart code of many libraries unreadable and messy.

@DartBot DartBot added Type-Defect area-language New language issues should be filed at https://github.com/dart-lang/language labels Feb 14, 2015
@pq
Copy link
Member

pq commented Feb 26, 2016

We've added @protected to the meta package. Hints implemented in analyzer: #25841.

@pq pq closed this as completed Feb 26, 2016
@YasserOJ
Copy link

YasserOJ commented Sep 2, 2020

the @Protected new value is only emiting a warning
what it actually should be an error
I don't won't the project to be built if the warning appears

@zoechi
Copy link
Contributor

zoechi commented Sep 2, 2020

@YasserOJ you can configure the level yourself in analyzer_options.yaml

@YasserOJ
Copy link

YasserOJ commented Sep 3, 2020

thank you for the response @zoechi
is this feature provided in any of the examples in the flutter repository ?
I didn't find key the that I should add to make this hint an error (example: "missing_required_param: error")
it not even provided in : https://dart.dev/tools/diagnostic-messages#glossary

@YasserOJ
Copy link

thank you for the response @zoechi
is this feature provided in any of the examples in the flutter repository ?
I didn't find key the that I should add to make this hint an error (example: "missing_required_param: error")
it not even provided in : https://dart.dev/tools/diagnostic-messages#glossary

@larssn
Copy link

larssn commented May 10, 2022

thank you for the response @zoechi is this feature provided in any of the examples in the flutter repository ? I didn't find key the that I should add to make this hint an error (example: "missing_required_param: error") it not even provided in : https://dart.dev/tools/diagnostic-messages#glossary

A bit late, but the rule is called invalid_use_of_protected_member.

copybara-service bot pushed a commit that referenced this issue Sep 27, 2022
…3 revisions)

https://dart.googlesource.com/dartdoc/+log/6b8b1c46da9a..ce5bd271eda9

2022-09-27 srawlins@google.com Fix generic typedef pointing to typedef (#3193)
2022-09-27 srawlins@google.com Unnamed libraries (#3189)
2022-09-27 srawlins@google.com Make InheritingContainer._inheritedElements late final (#3191)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/dart-doc-dart-sdk
Please CC dart-ecosystem-gardener@grotations.appspotmail.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Dart Documentation Generator: https://github.com/dart-lang/dartdoc/issues
To file a bug in Dart SDK: https://github.com/dart-lang/sdk/issues

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md

Tbr: dart-ecosystem-gardener@grotations.appspotmail.com
Change-Id: I371d173b9225721274f4faf652b56ee4f9fa8082
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261461
Commit-Queue: DEPS Autoroller <dart-autoroll@skia-public.iam.gserviceaccount.com>
Commit-Queue: Devon Carew <devoncarew@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language New language issues should be filed at https://github.com/dart-lang/language
Projects
None yet
Development

No branches or pull requests

8 participants