Sdk: Add public and private access modifiers to language

Created on 7 Jun 2018  ·  26Comments  ·  Source: dart-lang/sdk

Hello everyone, I've been analyzing the answers they gave me in issue #33104 33104, and I'll summarize them in a single proposal, which I consider a necessity and the most important, since the translation is not exact, I'll explain it with a couple of examples:

  • The proposal is: Add the reserved word public and private only.

  • An example with flutter.

class CounterState extends State<Counter> {

  private int counter = 0;

  private void increment() {
    setState(() {
      this.counter++;
    });
  }

  private void decrement() {
    setState(() {
      this.counter--;
    });
  }

  public Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new RaisedButton(
          onPressed: this.increment,
          child: new Text('Increment'),
        ),
        new RaisedButton(
          onPressed: this.decrement,
          child: new Text('Decrement'),
        ),
        new Text('Count: $counter'),
      ],
    );
  }
}
  • An example with dart
class Person {

  private String firstName; 
  private String lastName;  
  private int age;        

  Person(this.firstName, this.lastName, this.age);

  public Map<String, dynamic> asMap() {
    return {
      'firstName': this.firstName,
      'lastName': this.lastName,
      'age': this.age
    };
  }

  String get firstName => this.firstName;
  String get lastName => this.lastName;
  int get age => this.age;
}

void main() {
  final Person x = new Person("Brayan", "Martinez", 23);

  print(x.firstName)
  print(x.asMap().toString());
}
  • I hope you like this new version, and can convince them, what remains is to decearle the greatest possible success.
area-language closed-not-planned type-enhancement

Most helpful comment

Dart is going to add more type safety, and we don’t want to add access modifiers cause of dynamics?..

Guys, we are migrating to flutter from awesome Kotlin and Swift, not from stupid js. Dynamics is bullshit, nobody never use it in big production apps.

Stop being js and just add modifiers, instead of ugly _ and @protected

All 26 comments

Retitled to highlight the request.

What's the problem this change would solve?

It's a good question, I think it's necessary, this proposal comes mainly for two reasons.

The first one is about the adoption and use of this technology, this I will explain in the following list:

  • If you are a programmer of languages such as: php, java, c #, kotlin, scala, groovy, swift, visual basic.NET, ruby, among others that implement this type of syntax, if dart implements this improvement, migrate to this language will be mui Thankful, this will attract more users of this language than this I am completely sure.

  • This type of syntax I consider a standard, because it is present in many other languages, and if you are accustomed to it, programming with this type of syntax can be very comfortable and intuitive, you can reuse knowledge and experience.

  • This type of syntax reduces the learning curve and consequently you will be productive with this language from day 1.

  • I recognize that the syntax of the script under _ has its advantages, but also have its disadvantages, the ideal is to have support for both implementations and have compatibility with previous versions and that the programmer choose which to use.

  • And ending with the list, I say that this syntax can be syntactic sugar, pleasing to the eye and personally I like it a lot.

The second reason, seeing it from a more technical point of view, is to make a language more secure, standard, nice to the programmer, with business vision and general purpose, this will be explained better in the following list:

  • By having the reserved words public and private the virtual machine of the dart language you will have, a special way to work on the attributes of a class.

  • If we think about the 4 principles of Object Oriented Programming as they are: inheritance, abstraction, encapsulation and polymorphism, this syntax will help to comply with the encapsulation principle more effectively, helping the language making it more robust, safe and reliable.

  • This type of syntax will help to model and work better with the.

  • If we work with patterns such as ddd, hexagonal architecture, defining domain objects can be done more pleasantly with this type of syntax.

Well I hope to convince and have been able to justify the proposal very well I hope this is a reality, what I have left is to give a greeting from here

Sounds like personal preference.
I doubt this is good enough a reason to change a language that is around for about 6 years.
Also there are lots of people who prefer how it is today.
I find public and private extremely verbose and would consider the change you propose a pain.

It's not the first time this has been requested, but we have no current plan to add such keywords.

There is a reason Dart does not use class based privacy.
Dart allows dynamic invocations. If you write dynamic x = someObject(); x.foo; then the foo access does not know the class of the object in x. It must work independently of that.
Now, if x has a class with a private foo, should that function then be found? That depends on whether the access x.foo is inside that class. If it's protected, then it depends on whether the access is inside a subclass of the declaring class. That adds a lot of overhead to dynamic accesses. It's not impossible, but it's just not something that the Dart language is well suited for.

The library based privacy that Dart has is allows us to syntactically detect private member accesses, and use renaming per library to allow a more efficient implementation of dynamic access.

If we ever add some other sort of privacy, it's more likely to be instance based than class based. That means that you can only access such members through this or super, which ensures that we always know the type of the receiver and we avoid dynamic accesses.

What a shame that this request is not taken into account, this was a necessary requirement to take the decision to create an ERP on this platform, I speak to you as an investor and it is unfortunate that it ends well, I will have to look at the copetence like Java or TypeScript

My sincere apologies for commenting on a closed issue from 2018.

I would like to see that too. It would make Dart almost perfect language.

In my opinion, at least the _ could have been named private (or package private). It's not only very ugly to use _, but also not verbose and not adoption friendly. Most of the developers working in other languages know what private means, but hardly everyone new to Dart can be sure what _ means without reading docs.

It sacrifices verbosity in favor of fewer letters to type, when in fact, most of the time on development is not spent on pressing keys on the keyboard but thinking about what to type. The difference between typing 1 character, to ~15 is not relevant to the project development time, even if you multiply it to 50000.

I did read and understood the concerns raised by @lrhn, but I find very useful to have the instance visibility concept available. I think the concern raised was mostly about how to detect visibility when you have inheritance. That would not be a problem if the language didn't allow inheritance (not even mixin, but compile time paste with traits) but only composition and interfaces.

If I was maintaining Dart, I would still consider adding package private as a minor and marking _ as deprecated, so in the next major or some years from now it could be removed.

I think it's important to note that this is actually not about syntax. You could choose lots of different syntactic forms for the same thing, but it's the underlying structure that matters.

When privacy is indicated in the name of a class member (for instance, using _foo rather than foo) then it can be enforced independently of static typing, essentially with no performance cost. This is the approach that Dart uses.

When privacy is indicated by a keyword in the declaration (say, private) and is _invisible at call sites_, it would be prohibitively expensive to enforce privacy for dynamic invocations.

It would also cause ambiguities, because you can have, say, two superclasses of the dynamic type of the receiver, each of which adds a private foo. They may have completely incompatible signatures and purposes, and, presumably, you would want to call the foo that you happen to know about (whereas the existence of the other one might come as a complete surprise), but you might just as well get the surprise.

It would be detrimental to modular development to say that it's an error for two classes with a subclass relationship to add a private method with the same name (because then you'd have to know about all private methods in your class hierarchy, including the ones that are written and maintained by someone else).

So you could claim that it's all about having a well-defined semantics for dynamic method invocations (and perhaps you would add "and I don't care about having dynamic at all"). But unless you want to ban dynamic invocations 100% from all your software (noting that Java and C# _added_ support for some dynamic features), the fact that you cannot enforce privacy takes away a substantial amount of software robustness:

If you create a complex library _L_, and anybody who wants to do so can go in and fiddle with the values of your private variables and call your private methods etc, then I think it might be harder for you to maintain _L_, and to interpret bug reports and so on. OK, you have a private variable called foo, and the client's huge program does have a dynamic invocation of a setter named foo, but how do you know that the client is touching _your_ foo and messing up some invariants that _you_ need to maintain? It only takes _one_ dynamic invocation in a huge program to raise that question.

No idea why scope wouldn't be included and explicit. Flutter & Dart have some great things going on, but the things that are... odd?... are REALLY odd. And some of its verbosity for simple things is a little silly, while CHOOSING to leave out explicit scoping just seems like a poor choice. Same with inner classes. * shrug *

PHP is a very common scripting language used in the industry, in my opinion it is a worthy example to follow for the syntax of public and private the way of doing things in php is very intuitive and is very similar to java or c# with less verbosity of course, PHP continues to triumph in web development where the issue of verbosity and framework is attacked much like laravel hasen that php is very nice

@eernstg

I think it's important to note that this is actually not about syntax. You could choose lots of different syntactic forms for the same thing, but it's the underlying structure that matters.

If the underlying structure is what matters, let's choose a way to express the concept that is more familiar to everyone and looks less like an identifier naming standard.

It would also cause ambiguities because you can have, say, two superclasses of the dynamic type of the receiver, each of which adds a private foo. They may have completely incompatible signatures and purposes, and, presumably, you would want to call the foo that you happen to know about (whereas the existence of the other one might come as a complete surprise), but you might just as well get the surprise.

I don't buy this argument. If it is private you are not supposed to call or know it exists from an external perspective.

you'd have to know about all private methods in your class hierarchy, including the ones that are written and maintained by someone else

You don't have to know all private methods in your class hierarchy. That is not an issue in any OOP language and I don't see why it would be in Dart.

OK, you have a private variable called foo, and the client's huge program does have a dynamic invocation of a setter named foo, but how do you know that the client is touching _your_ foo

I think what you are understanding by private is what I understand by protected. Are you assuming private members would be accessible by inheriting classes?

This makes a lot of difference in the discussion because if private is only available within the class, it should never be accessible even if done dynamically.

I think as @Ing-Brayan-Martinez mentioned, you should take a look at how it works on PHP (and private works the same way in Java, Kotlin). I quote from PHP manual:

  • Class members declared public can be accessed everywhere.
  • Members declared protected can be accessed only within the class itself and by inheriting and parent classes.
  • Members declared as private may only be accessed by the class that defines the member.

I think Dart does not need to support (as described above) such protected behavior

Maybe we can avoid inheritance at all in favor of composition?

@fabiocarneiro wrote:

let's choose a way to express the concept that is more familiar

I understand that this kind of familiarity can be seen as attractive (especially for developers who are working in a highly heterogeneous environment), but at this point it would be a massively breaking change to switch from the _ name prefix to a private modifier in Dart. The name prefix ensures that it's obvious at use sites which member accesses are private, which I think is useful, and others might consider it more important to avoid the visual noise of _. But let's separate the syntax from the semantics (the syntax discussion will never end, anyway ;-).

It would also cause ambiguities ..

.. If it is private you are not supposed to call or know it exists

Dart private methods support overriding because the scope of privacy is the library (so you can have a class hierarchy with normal method overriding applied to private methods). In that sense, Dart privacy is "module privacy", somewhat similar to the Java notion of being package private.

This means that you cannot just choose to jump directly to the statically known implementation of a given private method, and this means that there must be _some_ mechanism that enforces the distinction between the private foo method from library _L1_ and another private method foo from library _L2_ (that may be present in the same instance because a class from _L2_ can have a class from _L1_ as its superclass).

When the _name approach to privacy was chosen (long time before I joined the Dart team) it was a major factor that the strict enforcement of this distinction could be implemented with no run-time performance penalty. (Basically, names of the form _foo can be mangled to include a unique part denoting the enclosing library, in declarations as well as invocations; that step must be applied to every occurrence of a private name, and if it is applied to any non-private name then it breaks the semantics. Of course, the language specification describes this in very different terms, but the name mangling approach is a very good model for understanding how it works.).

In PHP, the privacy scope is the class, and it's sufficient to compile private methods such that they check that the call site is in the same class (and for protected: that the receiver of the caller has a type which is a subtype of the enclosing class). But even that is a performance penalty, and I don't think such an approach (had it worked in Dart) would have been accepted for Dart. The fact that PHP privacy violations arise at run time demonstrates that there is a dynamic check, and that never has a cost of zero.

So my point was that we cannot accept this kind of ambiguity, but with a private modifier approach we will have it unless we accept a performance penalty for privacy related checks.

I think what you are understanding by private is what I understand by protected.

Protected is usually associated with the subclass hierarchy and unrelated to the module structure (in Dart: library structure), but you are right that privacy in Dart does include overriding relationships, which is not the case for class-based privacy.

So the source of confusion may be that what I understand by private (in this context) assumes a relationship with privacy in Dart.

I think Dart does not need to support (as described above) such protected behavior

If this is a proposal for dropping the current notion of privacy in Dart (library scoped privacy) and replacing it by a class scoped notion of privacy then we're looking at an even more massively breaking change.

On the other hand, it would be possible to _add_ a completely new notion of class scoped privacy for members, and it could use a private modifier. The protection against (statically checked as well as dynamic) invocations of such a method from anywhere outside the class could be achieved by name mangling, and that could also be used to prevent overriding. The compiler would be allowed to compile call of such methods into a direct jump.

class C {
  C next;
  private int foo() => next != null ? next.foo() : 42;
}

var x1 = new C().foo(); // Compile-time error.
var x2 = (new C() as dynamic).foo(); // Dynamic error.

This notion of privacy would compete with another one where invocations of private methods are restricted to have the receiver this (so this is _object_ scoped privacy). It's not obvious to me which variant of those is more useful in practice (and maybe the answer is just "that depends"), and it's also not obvious to me that we'd want to have a large number of mechanisms in this area. So that's a delicate topic.

Finally, it might seem more natural for Dart to build on top of the existing privacy mechanism (and enforce that private methods have names of the form _..., because they are subject to the usual library privacy constraints and guarantees, plus some extras). But I won't even mention that. ;-D

Thanks for the patience, and I need to say that I love this discussion.

In the Dart context, Private means something else, but for me and others, when we request this feature, we always mean "object scoped privacy"

Java package-private is also probably not the best name for this concept of visibility within a library. The absence of the modifier is what declares Package-private in java, and if you compare to the other modifiers, it behaves much more similarly to Protected than to Private. Protected is the same, but also allow visibility from other packages. That said, If I were giving it a name on the Java context, I would call it package-protected instead of package-private.

The same reasoning can be applied to Dart, as the _ is closer to protected (or package-protected) than to private. Updating that in the documentation would probably be beneficial to avoid new developers to have different expectations for the _. As an example, I would propose something like the following:

In Dart, there is no concept of private visibility, but package-protected can be defined by _.

That said, what all of us are requesting here is the introduction of a private keyword and it can be a completely new feature. If it wouldn't imply any performance impact, the _ can be left untouched, and there is no backward compatibility break.

Then the question is: Can this private modifier be implemented without performance impact? The way I see, it is a very straightforward process to detect in compile-time the call to Private members from external places. In the Dynamic contexts, I can see there might be a check to see if the member is visible or not, but isn't that the same check as seeing if it exists or not? Isn't the difference that now the list of existing methods would be a list of visible methods?

For me, the source of your concerns would be the introduction of a "protected" keyword, and that is NOT what we are asking.

One important factor here is also not only the performance but how likely people are to adopt the language. It is true that Dart is a huge success, but I also can see a lot of people complaining about its design choices. In the end, if people are not willing to adopt the language, its performance does not matter. In the end, we can all be writing code in assembly to achieve such great performance.

Thanks!

Tomorrow is a holiday here, so I'll just add a short remark and then go home ;-)

A private modifier could be implemented as a name mangling scheme which makes it impossible to call a private method foo outside the class C that declares it, even dynamically.

The tricky part is that this would make it hard to deal with (e as dynamic).foo() _inside_ C: It might be intended to call the private method on that receiver, and if we mangle foo for that call then it will indeed call that private method on an instance of C or any subclass thereof, and it won't call any other private method (so the "no overrides" still holds). But it might also be intended to call some other (non-private) method named foo. So if we're willing to somehow choose explicitly at the call site, for a dynamic invocation, whether it's a private or a public call, then we can obtain a consistent semantics. Otherwise that corner is a mess. ;-)

If you love clean-code like me, then you hate the _. It makes code difficult to read. Also, I don't see many uses for dynamic (in regular Flutter code, at least). Me and my team never use it.

For me it would be enough if private worked for typed variables, and then be ignored for dynamic ones. It would be a way for you to access private variables if you wanted, much like today you can mark something as @protected but still access it if you want.

In other words, private and protected keywords could work just like @private and @protected annotations.

Or at least we could have a @private annotation: https://github.com/dart-lang/sdk/issues/41089

Dart is going to add more type safety, and we don’t want to add access modifiers cause of dynamics?..

Guys, we are migrating to flutter from awesome Kotlin and Swift, not from stupid js. Dynamics is bullshit, nobody never use it in big production apps.

Stop being js and just add modifiers, instead of ugly _ and @protected

Access modifiers, please.

You want more people to join Dart and Flutter? Show that you care about them. Access modifiers are an important part of Object Oriented Programming, and just saying "we prefer this way" just denote you are not about end users, but only about the closed community developers working on Dart/Flutter who take the naming decisions.

I have more poor naming decisions to point out, among them, Padding(padding), Opacity(opacity), instead of Padding(value), Opacity(value). Saying "the padding of the Padding" and "the opacity of the Opacity" is redundant, and we are supposed to be against redundancy.

I've read all the reasons for not using access modifiers and going the "everything is public, unless you use underscore" route. There are all non-sense.

Then, there are decorators (meta tags) to tell that something is protected... so, why going the meta tags route, instead, of, erm.... using private, public, protected keywords, like the rest of the OOP languages???

It's like saying "Hey, everyone, notice me! I'm different! Everyone else is going right, but I'm going left because...reasons! Durr durr!"

Like the comment above me: Stop being js and just add modifiers, instead of ugly _ and @Protected.

We need a way to modify accessibility of classes because in favor of Flutter.
I create too many widget classes and in huge projects being able to import anything from anywhere is not the best thing. Also I don't like the _ prefix because it's not very readable and slowing down the typing.

For me, the most obvious thing to have as functionality is having a way to modify accessibility scope of some classes into a specific folder. This is very common case IMHO, e.g. you have a Screen widget, there are state class(es) file(s) related to it, there are widgets related to it and goes on... I don't want to import anything from there to other Screen classes. I think this is very common concept every Flutter developer faces during development.

Golang has best design choices for this topic, you can borrow some concepts from it. Uppercase => public, not slowing down the typing. Don't wanna import anything from anywhere => create another package.
But of course Dart should have its own way to handle this.

I may open proposal issue for this.

@eernstg
Thanks for all the info on why underscore was used.
Wondering though, would it be a problem to leave underscore for modular privacy and implement class or instance privacy using a private keyword? Would that no longe require the name mangling and avoid a lot of the problems with dynamic as it won't be able to overwritten or called from outside the class?

I think class privacy would have the same issues as library privacy. Instance privacy could presumably be enforced for dynamic invocations (say, when generating native code) by (1) checking whether the callee is instance private and, if so, (2) throwing unless the receiver in the previous activation record is the same as the receiver in the new activation record. However, that may not be cheap (for instance, the receiver may be stored in a register and may have spilled into any location of the previous activation record).

It would probably be more useful to decide up front that some kinds of access control will guarantee enforcement, so they can be used for optimizations and other "hard" purposes. Others are just used to emit diagnostic messages when it's known that there is a violation, and we accept that there can be a number of violations that won't be detected. The latter kind is useful as an aid in the approximate enforcement of certain software engineering properties.

Absolutely wild that this is considered "closed not planned" considering its ramifications for development. If I want to create a private method that should not be used by other classes in the package I have no options in Dart except for communicating its private nature to team members. If nothing else, this also clutters code completions.

While no code is truly self-documenting, this absence means that Dart code cannot approach self-documenting.

There’s always early 90s Visual Basic notation of “p__” on private variables.

FWIW I’ve decommissioned one flutter project this year. I think management is considering another for next year.

On Oct 24, 2020, at 4:13 PM, lmcdougald notifications@github.com wrote:


Absolutely wild that this is considered "closed not planned" considering its ramifications for development. If I want to create a private method that should not be used by other classes in the package I have no options in Dart except for communicating its private nature to team members. If nothing else, this also clutters code completions.

While no code is truly self-documenting, this absence means that Dart code cannot approach self-documenting.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

Interesting that nobody has been able to give any concrete example as to what problem class privacy would solve. Seems to me that they just want to change Dart to work with their current coding practices rather than learn how to use Dart effectively.

In Java you have a class per file and things marked private are accessible only in that file. In Dart, each file is a library and anything with an underscore is only accessible in that file. ¯\_(ツ)_/¯

My concerns about accessibility can be solved better with Inner Class: https://github.com/dart-lang/language/issues/336. I don't care about private or public keywords, the main concern here is huge namespace that caused with let's say thousands of Classes you create within the project.

@tobega I believe such topic does not need examples. Everybody know what we are talking about. But if you want:

Instead of

User _user;
@Protected
Car car;

I suggest default syntax from C-family languages:

private User user;
protected Car car;

"they just want to change Dart to work with their current coding practices"

Some things are done well in other languages. We are not lazy, we are able to change our habits and practices. So we don't want to just change the language. I believe the approach with access modifiers from Kotlin/Swift/Java is more natural and more beautiful than "Hungarian notation" in Dart.

In android we write every member from "m", mUser for example (Google force this practice). And this is ugly, even if it written on Java or Kotlin. And the same with "_" prefixes and @Protected annotation in Dart.

"More beautiful" is an opinion not a fact. It is not convincing at all.

On Tue, 17 Nov 2020 at 21:09, Pavel Shorokhov notifications@github.com
wrote:

@tobega https://github.com/tobega I believe such topic does not need
examples. Everybody know what we are talking about. But if you want:

Instead of

User _user;

I suggest default syntax from C-family languages:

private User user;

"they just want to change Dart to work with their current coding practices"

Some things are done well in other languages. We are not lazy, we are able
to change our habit's and practices. So we don't want to just change
language. I believe approach with access modifiers from Kotlin/Swift/Java
is more natural and more beautiful than "Hungarian notation" in Dart.

In android we write every member from "m" (mUser) for example (Google
forced this practice). And this is ugly, even if it written on Java or
Kotlin. And the same with "_" prefixes in Dart.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/dart-lang/sdk/issues/33383#issuecomment-729172771,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AGACJ54S7XWAPJSSHR73BT3SQLJ7RANCNFSM4FD23YCQ
.

Was this page helpful?
0 / 5 - 0 ratings