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

Class should have a primary constructor #138

Closed
pedromassango opened this issue Dec 17, 2018 · 14 comments
Closed

Class should have a primary constructor #138

pedromassango opened this issue Dec 17, 2018 · 14 comments

Comments

@pedromassango
Copy link

Why not to have a primary constructor?
This way:

class Person(String firstName, Int age) { 

    // primary constructor initialization (optional)
    init{

    }
}

Is better than this:

class Person { 

String firstName;
int age;

    Person(this.firstName, this.age){
        // constructor initialization
    }
}

As you can see in Dart we need to create the property inside de class and then call in our constructor, would be good to create the property inside the primary constructor as we touch the property only once and it will be available in whole class.

@munificent
Copy link
Member

munificent commented Dec 17, 2018

I don't think the fields should be right after the class name. In many cases, there is too much other syntax already right there. The class name may be long, may have type parameters (which may have bounds). There can be an extends clause, implements clause (with possibly many interfaces), and an on clause (again, possibly with many mixins).

Stuffing fields in there too is a lot of syntax to get through before you hit the {. This makes it harder to find the field declarations, and discourages users from writing doc comments for them. The latter is, I think, particularly problematic.

@pedromassango
Copy link
Author

Have you used Kotlin?

@munificent
Copy link
Member

munificent commented Dec 18, 2018

Some, yes. I've also read a bunch about a number of other languages that do primary constructors, as well as designing a hobby language or two that work that way. I think it's nice for small classes, but it scales up poorly.

@yjbanov
Copy link

yjbanov commented Dec 18, 2018

I agree that this syntax doesn't scale well to arbitrary classes. However, it would be very useful for things like complex return types. There's an alternative proposal for this, but I think if we had a low-boilerplate solution for declaring "value"/"data" classes we wouldn't need multiple return types or primary constructors.

If we get immutability with a nice syntax and good semantics I think we will solve this issue as well.

@mraleph
Copy link
Member

mraleph commented Dec 19, 2018

I think it's nice for small classes, but it scales up poorly.

Conversely things that scale to large classes are usually too unwieldy for small classes.

I think there is a value giving developers an ability to declare small classes without pages of ceremonious code.

@pedromassango
Copy link
Author

@munificent Think of me, Kotlin's way and the current Dart way, which one do you think is best for classes with more than 10 parameters?

The Dart way the developer has to write so much unnecessarily. Take a look at Kotlin's way and I think you'll give me some reason.

@yjbanov
Copy link

yjbanov commented Dec 19, 2018

@mraleph

Conversely things that scale to large classes are usually too unwieldy for small classes.

You are as good at minimizing the number of words to express something that takes 5x the number of words for me, as you are at minimizing the number of CPU instructions to express programs 😄

@munificent
Copy link
Member

I think there is a value giving developers an ability to declare small classes without pages of ceremonious code.

I agree, but I like it best when those features scale smoothly to larger use cases. Many classes that start small end up big, and it's no fun if you have to eventually discard the primary constructor syntax and rewrite the entire class using the other syntax. Incremental changes to a class should require incremental changes to the program text.

For example (I haven't put more than five minutes of thought into this), we could say that if you define a class like:

class Person {
  String firstName;
  int age;
}

Then it implicitly gets a constructor that takes those fields as named (or maybe positional?) parameters. This gives you an easy way to get a small class up and running. If you later decide to do some validation, you can add a constructor, but you never have to rearrange the code to move the fields out of a primary constructor and into the body.

@chimon2000
Copy link

Just for comparison sake, here's how typescript handles constructors

class Person {
    constructor(
        public firstName: string,
        public age: number,
        private somePrivate: string = 'no access'
    ) {}
}

const aPerson = new Person('Bob', 22)
aPerson.firstName //Bob
aPerson.somePrivate //Error

The access modifier can be specified in the constructor, which gets rid of some of the redundancy. A similar Dart example may be something like

class Person {
    Person(
        String firstName,
        Int age,
        String _somePrivate = 'no access'
    );
}

//or mirroring the initial suggestion even

class Person(
        String firstName,
        Int age,
        String _somePrivate = 'no access'
    ) { }

@munificent
Copy link
Member

class Person {
    Person(
        String firstName,
        Int age,
        String _somePrivate = 'no access'
    );
}

Well, that's already valid Dart syntax for defining a constructor that takes some parameters but does not define them as fields. We can't just ignore the access modifiers in TypeScript, because it's those exact modifiers that the language uses to distinguish between class fields and constructor parameters. We'd have to come up with some sort of marker syntax in Dart. We don't want all constructor parameters to turn into fields.

@chimon2000
Copy link

That makes sense, I know that JavaScript will be using # to identify private variables. I'm not familiar with the reasoning for that choice. The use of public / private is more explicit.

@derolf
Copy link

derolf commented Jan 24, 2020

Please either adopt the syntax of:

  • Scala case classes
  • Kotlin data classes
  • Typescript constructor instance parameters

No need to invent something completely new!

@kevmoo
Copy link
Member

kevmoo commented Jun 17, 2020

See #698 – I think gets you where you want to go!

@leafpetersen
Copy link
Member

We're tracking this request here, closing in favor of that issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants