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 public and private access modifiers to language #33383

Closed
Ing-Brayan-Martinez opened this issue Jun 7, 2018 · 66 comments
Closed

Add public and private access modifiers to language #33383

Ing-Brayan-Martinez opened this issue Jun 7, 2018 · 66 comments
Labels
area-language Deprecated: New language issues should be filed at https://github.com/dart-lang/language closed-not-planned type-enhancement

Comments

@Ing-Brayan-Martinez
Copy link

Ing-Brayan-Martinez commented Jun 7, 2018

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.
@Ing-Brayan-Martinez Ing-Brayan-Martinez changed the title Rethinking the proposal # 33104 for Dart 3.0 Rethinking the proposal #33104 for Dart 3.0 Jun 7, 2018
@vsmenon vsmenon added the area-language Deprecated: New language issues should be filed at https://github.com/dart-lang/language label Jun 7, 2018
@vsmenon vsmenon changed the title Rethinking the proposal #33104 for Dart 3.0 Add public and private access modifiers to language Jun 7, 2018
@vsmenon
Copy link
Member

vsmenon commented Jun 7, 2018

Retitled to highlight the request.

@zoechi
Copy link
Contributor

zoechi commented Jun 8, 2018

What's the problem this change would solve?

@Ing-Brayan-Martinez
Copy link
Author

Ing-Brayan-Martinez commented Jun 9, 2018

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

@zoechi
Copy link
Contributor

zoechi commented Jun 10, 2018

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.

@lrhn
Copy link
Member

lrhn commented Jun 11, 2018

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.

@Ing-Brayan-Martinez
Copy link
Author

Ing-Brayan-Martinez commented Jun 30, 2018

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

@fabiocarneiro
Copy link

fabiocarneiro commented Mar 7, 2019

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.

@eernstg
Copy link
Member

eernstg commented Mar 7, 2019

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.

@chornbe
Copy link

chornbe commented May 26, 2019

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 *

@Ing-Brayan-Martinez
Copy link
Author

Ing-Brayan-Martinez commented May 28, 2019

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

@fabiocarneiro
Copy link

fabiocarneiro commented May 28, 2019

@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?

@eernstg
Copy link
Member

eernstg commented May 29, 2019

@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

@fabiocarneiro
Copy link

fabiocarneiro commented May 29, 2019

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.

@eernstg
Copy link
Member

eernstg commented May 29, 2019

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

@marcglasberg
Copy link

marcglasberg commented Mar 18, 2020

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: #41089

@comm1x
Copy link

comm1x commented Mar 26, 2020

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

@angelhdzmultimedia
Copy link

angelhdzmultimedia commented May 7, 2020

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.

@esenmx
Copy link

esenmx commented Jul 8, 2020

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 a proposal for this.

@shbi
Copy link

shbi commented Sep 9, 2020

@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?

@eernstg
Copy link
Member

eernstg commented Sep 10, 2020

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.

@lukemcdo
Copy link

lukemcdo commented Oct 24, 2020

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.

@chornbe
Copy link

chornbe commented Oct 24, 2020

@eernstg
Copy link
Member

eernstg commented Feb 9, 2021

I would suggest that a system of Request for comments is also introduced

We had a notion of a 'DEP' (Dart Evolution Proposal), e.g., dart-archive/dart_enhancement_proposals#30. But we decided that the added formality and process wasn't contributing much value, and hence today's discussions take place in the language repo.

@fabiocarneiro
Copy link

fabiocarneiro commented Feb 9, 2021

@eernstg Creating a PDF that follows a template seems to be a bit cumbersome. I'm not surprised people weren't very happy about it.

The PHP system has a wiki-like page that after you get granted permissions, you can just press a button to create a new page and everything is done through the system. A more simple approach could be just creating a markdown file on a specific repo, and perhaps have a page that parses and displays it in a more beautiful way.

The main reason I am suggesting this is because of the voting system it provides. It democratizes the decision of what gets in and what doesn't. Rather than one or two maintainers participating in an issue, many relevant contributors can participate. Example of one that was rejected by the community https://wiki.php.net/rfc/match_expression

@chornbe
Copy link

chornbe commented Feb 9, 2021

@fabiocarneiro
Copy link

fabiocarneiro commented Feb 9, 2021

@chornbe The suggestion was not to allow anyone to vote and I personally think it would be a big mistake. There needs to have some level of activity in the community and a deep understanding of the language and implications of your vote. The suggestion was more towards making it more transparent, traceable, and have a little more than one or two maintainers deciding on the language future. Let's say a group with the 30~50 most active Dart project maintainers?

@Ing-Brayan-Martinez
Copy link
Author

Ing-Brayan-Martinez commented Feb 9, 2021

Good morning, I am reading your comments in this productive debate and thought about responding to your comments as follows:

  1. I think that creating a forum where the community can propose and vote on the new features of language is the best idea I've heard, this is what the PHP community does with RFC, or Javascript with TC39, or OpenJDK with JEPs. This forum could be accessed from the official dart.dev website
  2. On the other hand I think that the reserved word private should be an alias _x to be able to have compatibility with previous versions and the existing library ecosystem
  3. And finally I communicate my willingness to participate in this group, forum, or what dart language development team decides to create, it would be an honor to be able to contribute to this wonderful community

Without more to say I bid you farewell, have an excellent day

@eernstg
Copy link
Member

eernstg commented Feb 10, 2021

@fabiocarneiro wrote:

Creating a PDF that follows a template seems to be a bit cumbersome

That wasn't required, but the whole process was a bit more formalized. However, voting for a feature is done (in addition to adding comments) by clicking 👍 on the initial comment on the issue, and that is certainly already part of the discussions about the evolution of the language.

@fabiocarneiro
Copy link

fabiocarneiro commented Feb 10, 2021

That wasn't required, but the whole process was a bit more formalized. However, voting for a feature is done (in addition to adding comments) by clicking on the initial comment on the issue, and that is certainly already part of the discussions about the evolution of the language.

Right now then we have 26 votes in favor, 3 against, and 6 hearts. Would that be enough to assume the language should move in this direction?

Who voted for it? Which votes should be considered? What are the requirements to belong to this group? When and where does the voting take place? What if I remove or modify my reaction after the event takes place? What does it mean if I react with a 👯 ? Is a tooltip a convenient way to inspect the results?

It is very different than this:

DeepinScreenshot_select-area_20210210130138

If something was rejected, perhaps an additional pool is useful to address the concerns in a future proposal:

  1. Not interested
  2. I don't want blocks
  3. Missing return values in blocks
  4. Missing pattern matching
  5. Missing explicit fallthrough
  6. BC break is not acceptable
  7. Wanted switch expressions instead
  8. Other

DeepinScreenshot_select-area_20210210130224

@proshin-roman
Copy link

proshin-roman commented Mar 13, 2021

Sorry, I don't know the actual status of this issue (still "closed"?), but I just came to Dart&Flutter universe. I have huge experience in Java, also started learning Swift that by itself looks very nice (I'm talking about the language only though). But I had to switch to Flutter just because I want to have multiplatform mobile applications without from the beginning. And then I faced this ugly solution with using _ symbol to mark private fields/methods. Sorry, but that's so ugly, it reminds me some bad PHP code and just shows that the language is not able to explicitly define intentions of developers (and that's already mention by a number of articles).
I definitely would like to have an explicit private keyword - at least just as a replacement for _ symbol. The first argument for that (that lies on the surface) is that changing the visibility currently forces me to do renaming operation 🤦
So, I hope this feature will be considered at some point.

@MatrixDev
Copy link

MatrixDev commented Mar 18, 2021

also t would be great to have package access modifier... not everyone likes to work with files 50k lines each just to reduce visibility...

@huylethanh
Copy link

huylethanh commented Mar 24, 2021

Dart should has the access modifier. a thing is uncomfortable is when I have a class, the variable is private "String _abc" and it is being called many places in the class, then i want to public that variable, i change it to String abc. i have to change that name in entier class. If we have the public and private keywork, we just change only one place. Please add access modifier. And the same request for method.

@CostachescuCristinel
Copy link

CostachescuCristinel commented Apr 13, 2021

You guys are making this a longer discussion than it needs to be.
This could have been ended quite sooner if the request was made and undestood by everyone like this:

Implement a keyword private that annotates identifiers as being library private - effectively doing the same work that _ (underscore) does now.

Basically, what most people were looking for was to be able to write this:

class Example {
    private int foo = 5;
    ...
}

instead of:

class Example {
    int _foo = 5;
    ...
}

No need for a public keyword, any identifiers not marked with private would be public by default - as it is current behavior.
Introducing this does not require any additional dynamic checks that were discussed at the beginning of the discussion, nor behavior changes in the Dart core. In fact, the behavior would be the same with the added benefit of improved code readability.

You might argue that you would have to clarify in the docs that the private keyword in Dart does not mean the same thing as it does in other languages.
Right... imagine having to explain in your docs that, not only Dart has private identifiers, but that they are only private to the library, not to the class defining them; and it also uses an underscore-prefixed identifier to mark such private identifiers.
Yup, you got yourselves fooled, twice.

This discussion reminds me of JavaScript's private class fields proposal, equally long and unnecessary, and they still chose the worst option.

Anyway, just my 0.02$...

@MatrixDev
Copy link

MatrixDev commented Apr 13, 2021

@CostachescuCristinel there are a lot of comments to add package, protected etc.

@chornbe
Copy link

chornbe commented Apr 13, 2021

@CostachescuCristinel
Copy link

CostachescuCristinel commented Apr 13, 2021

@MatrixDev I would agree with them on looking after such language features, for good OOP reasons I'd add. But this could be a topic for another discussion. As far as I can see, the initial requests were only about getting rid of that underscore notation in favor of an explicit private keyword (with public thrown in the mix for completeness I guess, but could've been disregarded as well).

Anyway, I'm not going to make this discussion any longer. I ended up here from the Dart language tour, and I was just amazed by the lengthy discussion. My best regards and good luck to you all :)

@PapaNappa
Copy link

PapaNappa commented Jul 28, 2021

From what I can see, there are two major points in favour of the _ as opposed to a private modifier:

  • Dynamic calls

    Add public and private access modifiers to language #33383 (comment)
    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.

    I get that point and it makes a lot of sense.

  • Overriding private members

    Add public and private access modifiers to language #33383 (comment)
    Dart private methods support overriding because the scope of privacy is the library […]. 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 […].

    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. […]
    […]
    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.

    This reasoning also seems fair, given the goal of speed.
    However, public method calls are also quite common (would like to see a statistics), so how much impact does this optimisation have that’s only applicable for private access, and the runtime check is needed for public access anyway?

But having a look at the "greater structure", I feel there are higher priority points that favour a private modifier.
(I get that this is very late in the development of Dart and things likely don’t change, but I think it’s still a valuable discussion.)

What are the benefits of having dynamic calls in productive code or for productive coding?
In my experience, a sloppy coding style to "just test something out" leads very quickly to a worse coding productivity and less robust, maintainable code.
What are the use cases for "especially dynamic" code?
I think the benefits of true static type checking outweigh the benefits of dynamic typing.

In a similar manner, what are the benefits of allowing overriding private members? Most languages don’t allow this (or mark them using the protected keyword, not some marker), and even if allowed, the rare use cases could justify a small performance hit.
Is this really such an important feature that it warrants such inconsistent and unusual approach?

Again, looking at the greater structure, having a property of a field encoded in the name is a bit obscure.
Having _ for one single purpose is inconsistent with the rest.
From the perspective of robust and clean, maintainable code, following "best practices" of similar languages seems more important than specialty features such as private member overriding.

From Dart’s overview page:

The Dart language is type safe; it uses static type checking to ensure that a variable’s value always matches the variable’s static type. Sometimes, this is referred to as sound typing. Although types are mandatory, type annotations are optional because of type inference. The Dart typing system is also flexible, allowing the use of a dynamic type combined with runtime checks, which can be useful during experimentation or for code that needs to be especially dynamic.

This also seems a bit contradictory. What is Dart, statically typed or dynamically typed? Can you reasonably have both?

If Dart prefers to be dynamically typed, and values highly-efficient private member overriding over de-facto standards from other languages, so be it.
But advertising "sound null-safety" and "static typing" where the type "always" matches might be misleading, resulting in such discussions.

@MatrixDev
Copy link

MatrixDev commented Aug 10, 2021

@scbabacus-midnight you can't compare Kotlin multi-platform with Dart. Dart is mostly used in combination with Flutter. Kotlin at this moment doesn't have even a fraction of platform-specific functionality nor libraries as Flutter does.

As I suggested previously Dart can have both - static and dynamic typing (adding private/protected/public without removing _). so you can write both ways:

  • void _myPrivateFunction()
  • private void myPrivateFunction()
    The only limitation would be that you're not allowed to write public void _myPrivateFunction().

PS: this argument can go the other way as well - you're not the only one, a lot of people would love to have proper static typing.

@midnight-wonderer
Copy link

midnight-wonderer commented Aug 10, 2021

@MatrixDev Thank you for @ me. I just realized I used a work account to express opinions.
Let me switch to my account. (Sorry for the noise everyone on the list)
As PapaNappa mentioned, there is no point in discussing what to do now, not gonna happen. I just respond to the called for dynamic typing use cases.

Original post:

FWIW
I prefer dynamic typing; different people solving different problems.
I would disagree with a lot of things in Dart but understand that they are solving their problems.

For me, "dynamic typing" can also mean "interface everywhere".
If someone else implements something that accepts dynamic-typed parameters, I can always implement another object with the same signature they expected without modifying other people's classes to declare an interface.
And those interfaces will be possible everywhere, even unintentional.
And that's how the Ruby community works together while still agnostic to other people's code.
(I know, in Dart, a class can implement another class; that's weird, btw)

So no, not everyone is on the static-typing camp. And just because you cannot be productive in a dynamic-typing environment doesn't mean everyone does.

From what I observed, Dart is a machine-oriented language. The people behind Dart care deeply about performance and optimization. They design the language, so it is easy to optimize. (take const keyword as an instance, and they are openly doing it all over the place)
Average people don't even have to care about the performance that much.

The Dart team will favor machines; there is nothing we can change about that; they are in their game and are good at it. After hearing their reasoning, I will accept Dart the way it is.
For people who prefer human-oriented language with static typing, I would recommend Kotlin. The language can build on many platforms now, even web apps; it is somewhat similar to Dart IMHO.

@pulstar
Copy link

pulstar commented Oct 5, 2021

@huylethanh

then i want to public that variable, i change it to String abc. i have to change that name in entire class. If we have the public and private keywork, we just change only one place.

In Android Studio and IntelliJ, just place the cursor over the variable name, where it is declared and type SHIFT + F6. You can also use this tool to rename methods and classes too. It will rename in the whole project.

@MatrixDev
Copy link

MatrixDev commented Oct 6, 2021

In Android Studio and IntelliJ, just place the cursor over the variable name, where it is declared and type SHIFT + F6. You can also use this tool to rename methods and classes too. It will rename in the whole project.

And you'll have huge diff in the commit if variable is used in multiple files. Also this might lead to merge conflicts.

@huylethanh
Copy link

huylethanh commented Oct 6, 2021

@huylethanh

then i want to public that variable, i change it to String abc. i have to change that name in entire class. If we have the public and private keywork, we just change only one place.

In Android Studio and IntelliJ, just place the cursor over the variable name, where it is declared and type SHIFT + F6. You can also use this tool to rename methods and classes too. It will rename in the whole project.

Yeah. I know that, but i meant we would change a lot of line. And when we commit the file. It's so hard for review the code changed.

@pulstar
Copy link

pulstar commented Oct 7, 2021

@huylethanh

Yeah. I know that, but i meant we would change a lot of line. And when we commit the file. It's so hard for review the code changed.

I agree. The PRIVATE keyword would be better.

@cedvdb
Copy link

cedvdb commented Dec 8, 2021

Interesting that nobody has been able to give any concrete example as to what problem class privacy would solve

Let's flip it around, I've not seen many use cases where _member is accessed from another class in the same file.

Like this:

class Test {
  final int _priv = 3;
}

class Also {
  Also() {
    print(Test()._priv);
  }
}

There are some use cases for public APIs, other languages have it too, like Java default access modifiers, where values can be accessed only within the same folder. The issue is that to have this feature, you have to put the classes in the same file, which is really intrusive and I would refuse to do. I find codebases where class are not separated into files harder to navigate, to each his own I guess.

Also features like this have some inconsistencies built into it because of the access modifier is part of the member's name

@CharlVS
Copy link

CharlVS commented Dec 12, 2021

@MatrixDev
Copy link

MatrixDev commented Dec 13, 2021

@CharlyZA-2, is it still open? Also this is the only place people can realistically debate and give their subjective opinions.

@cedvdb
Copy link

cedvdb commented Jan 11, 2022

There are objectives arguments to be made why access modifiers that give finer control, like "package private" (java) can make for better public api of "package". I'm using quotation mark here because I'm referring to java "package" not pub dev packages, that is folder. Just private, public and protected do not allow for this fine grained control. It is quite frustrating that the only way to have that is to put everything in the same file.

However I hope there is going to be some sort of module where the folders inside that module can access properties of said module while folders outside of the module cannot. Similar to what library is today but extended to multiple file.

There is the module proposal, which I'm not is about this or not. I've read in diagonal the proposal but it's lengthy and I did not get the sense that it was its primary focus. I hope I'm wrong.

@zoechi
Copy link
Contributor

zoechi commented Jan 13, 2022

@cedvdb use "part" and "part of"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Deprecated: New language issues should be filed at https://github.com/dart-lang/language closed-not-planned type-enhancement
Projects
None yet
Development

No branches or pull requests