What does the 'get' keyword do in a dart class? [duplicate] - flutter

I am struggling with the concept of getters and setters in Dart, and the more I read, the more I cannot grasp the underlying purpose. Take for example the following code:
main() {
Car car = new Car();
car.doors = 44;
print(car.doors); // 44
}
class Car {
int doors = 4;
}
Later, I decide to make “doors” a private variable, so I do the following:
main() {
Car car = new Car();
car.doors = 44;
print(car.doors); // 44
}
class Car {
int _doors = 4;
int get doors => _doors;
set doors(int numberOfDoors) => _doors = numberOfDoors;
}
According to the code, _doors is now a private variable, and so I cannot access it in main(). However, by manipulating doors, I can indirectly change the value of _doors, which is what I thought I wanted to prevent in the first place by making it a private variable. So what is the purpose of making a previously public variable into a private one, if you can still indirectly manipulate it? And, how are getters and setters even working to change the properties of these variables? I am trying to understand the fundamental concept, because without that, I don't understand how or why getters and setters are used.

Instance variables in Dart have implicit getters and setters. So for your example code, it will operate in exactly the same way, since all you have done is changed from an implicit getter and setter to an explicit getter and setter.
The value of explicit getters and setters is that you don't need to define both if you don't want. For instance we can change your example to only define a getter:
main() {
Car car = new Car();
print(car.doors); // 4
car.doors = 6; // Won't work since no doors setter is defined
}
class Car {
int _doors = 4;
int get doors => _doors;
}
Additionally, you can also add extra logic in a getter or setter that you don't get in an implicit getter or setter:
class Car {
int _doors = 4;
int get doors => _doors;
set doors(int numberOfDoors) {
if(numberOfDoors >= 2 && numberOfDoors <= 6) {
_doors = numberOfDoors;
}
}
}

The getter and setter functions allow us to make the class appear to have a property, without a explicit property being declared (_doors in your case). The property value may be calculated from other properties.
The getters and setters allow us to execute arbitrary code when the property is get or set.
Omitting a setter makes the property immutable.
An abstract class may declare getters and setters without bodies as part of a required class interface.

Related

Why is it necessary to use constructors in dart programming language classes?

I'm a beginner learning dart from the book dart apprentice and I reached where they were discussing constructors in dart classes, the book was implying that constructors create instances of the class which I understood but I needed more info about constructors. So I googled and some results repeated what was already in the book about it being used to create instances of a class while others also showed that it's used to instantiate class properties, but my problem is with the other answer which I found that they are used to instantiate properties of a class, but my question is: I instantiate all class properties when I create the class by declaring the property variables, like this:
class UserClass{
userClassProperty = "";
anotherUserClassProperty = ""; }
why is the constructor also needed to instantiate class properties?
Often, values are unique to every class instance.
Consider the following example:
class Point {
final int x;
final int y;
const Point(this.x, this.y);
double get distanceToOrigin => sqrt(x * x + y * y);
}
If the x and y values were defined inside the class, it would be pretty useless. Instead, different Point objects can be instantiated with different values, which means the same code can be used for different situations.
Ok, so constructors instantiate or start a class by collecting all the data the class needs to start to start working. Constructors are so important that the dart compiler provides one even if you don't explicitly create one. For example, you create a class for mammals like this :
class Mammal{
String name = "cat";
int numberOfLegs = 2;
}
Although you don't explicitly add a constructor the dart compiler adds a default constructor like this :
class Mammal{
Mammal(); //This is added by dart during the class instantiation by default.
String name = "cat";
int numberOfLegs = 2;
}
Yeah, that's how crucial constructors are to the dart compiler.
And on the topic of why are they necessary even when you declare all the properties by yourself in the class, as hacker1024 said it would make the class pretty useless, as the point of the existence of classes is to create variants but with different properties. Not adding a constructor to your class and defining all the properties in the class would mean that your class doesn't take property arguments which in turn also means that different variants of your class can't be created. Again this goes directly against the point of the existence of dart classes. For example, you have a class like this :
class Mammals{
Strig name = "Human";
int numberOfLegs = 2;
bool hasFur = false;
}
final cat = Mammal();
final human = Mammal();
print(cat.numberOfLegs); //Prints 2
//2
print(human.numberOfLegs); //Also prints 2
//2
print(cat.hasFur);
// false
Yeah, this class is problematic. Cats with 2 legs? You would agree with me that that's not how things are in reality. And also the class is pretty useless in the sense that it's not modular, no matter which kind of mammal we create be it a cat, a sheep or even a cow the name property is going to be the default one we set, that is "Human". When we create a class to simulate mammals we want to be able to define what kind of properties it has, not use some fixed values. So you want to create a class which has a constructor like this :
class Mammals{
Mammals(String name,int noOfLegs, bool hasFur){
this.name = name;
this.noOfLegs = noOfLegs;
this.hasFur = hasFur;
}
String name = "";
int noOfLegs = 0;
bool hasFur = False;
}
final cat = Mammal("Cat", 4, True); //Now you can pass in the properties ou want.
final human = Mammal("Human", 2, false);
print(cat.name); //This prints the customized name of the object cat instead of some fixed value
//Cat
print(human.name); //This prints the customized name of the object human
Now we have two instances of the class with separate property values.
Although this adds a little more code, the modularity benefit is worth it.

How to get properties of subclass in dart?

I have a class A with some properties:
abstract class A {
double doubleA;
String stringA;
...
A({this.doubleA = 0, this.stringA = ""});
}
and a class B with some properties, that extends class A:
class B extends A {
int intB;
String stringB;
B({
this.intB = 0,
this.stringB = "",
double doubleA = 0,
String stringA = "",
}) : super(doubleA: doubleA, stringA: stringA);
}
In my code I want to now check if an instance of A has a value that is of type of subclass B:
A a; // Value can be of different subtypes of A including B
if(a is B) {
// here dart should give me access to the properties of a like:
print(a.stringA);
// but it should also be possible to access the type B properties
// since the value of a can also be of subclass type B:
print(a.stringB);
}
This sounds wrong at first but I know that it can work because of examples in flutter.
Example Listener:
Listener(
onPointerSignal: (event) {
// event is of type PointerSignalEvent which has no property 'scrollDelta'.
// So print(event.scrollData); does not work here.
if (event is PointerScrollEvent) {
// if you check if event is of subtype PointerScrollEvent the property 'scrollDelta'
// that is included in the class PointerScrollEvent becomes available.
print(event.scrollDelta); // works without any problem.
}
},
}
However I have not been able to replicate this with my classes A and B and I don't know why it doesn't work. I have also looked into the implementations of these flutter classes and copied the class structure but I can still only access the properties of A after the check if(a is B) which doesn't correspond to the behavior observed with the flutter classes.
What am I doing wrong? Am I am missing something?
Thanks for reading :D <3
If you declare a variable 'a' as being of type 'A', you will not be able to access the properties of classes inheriting from A (like B).
Let's say A is Animal and B is Baboon. Baboon inherits properties from Animal, so all variables instantiated with the Baboon type with have access to properties from both classes. But variables instantiated with the Animal type will only have access to the Animal properties.
Here are some examples: https://medium.com/jay-tillu/inheritance-in-dart-bd0895883265

instantiate object with *new* keyword and use property inside class with *this* keyword

i'm coming from mainly JS/TS world (NestJS/Angular) and recently i start to building Flutter apps..
i have 2 main questions
there is any difference when instantiate object with or without new keyword?
i saw examples in flutter when people use new Row(children: [Text('Foo'), Text('Bar'),],) instead of just Row(...)
if there is a difference which one is better to use?
inside of my Dart classes in flutter app, i can both use this.property and property again there is any difference and if so which one is better and why?
example:
class Person {
final String name;
final int age;
Person(this.name, this.age);
getNameAge() => '${this.name} is ${this.age}';
getNameAge2() => '$name is $age';
}
both looks the same to me
void main() {
final p = Person('dan', 22);
final p2 = new Person('ben', 20);
print(p.getNameAge()); // dan is 22
print(p2.getNameAge2()); // ben is 20
}
The new keyword is optional in Dart and I think the general consensus is, today, to not use it.
The use of this is useful if you have multiple variables with the same name but in different scope. E.g. (this is just an example. You would not make a setA method in Dart but use properties):
class A {
int a;
A(this.a);
void setA(int a) {
this.a = a;
}
}
Here we use this to distinguish between the argument a and the class variable a. But if you don't have variables with the same name (but in different scope), the use of this is optional. In some projects, you still use this to make it more clear that you are referring to a class variable even if it is not needed.

Using Setters with Constructors in Dart

How can I use the setter of a private instance variable from the default constructor in Dart?
Given the example class:
class A {
String name;
int _age;
int get age => _age;
set age(age) {
_age = age ?? 0;
}
A(this.name, this._age);
}
How can I use this constructor to go through the set age() function? Is there away aside from using a factory? I'd like to do something like this
A(this.name, newAge): age = newAge;
But I get an error forcing me to only set instance variables from the constructor, which has me just duplicating the setter:
A(this.name, newAge): _age = newAge ?? 0;
Am I missing something or is this just not possible with dart?
The initialization list of a constructor can be used only to initialize members (or call base class constructors). (Additionally, when the initialization list is executed, this isn't valid yet, so you can't access any members.)
If you want to do other kinds of initialization work, you can do it in the constructor body instead, at which point the object is considered to be sufficiently constructed for this to be valid:
A(this.name, int newAge) {
age = newAge;
}
Also see:
Difference between assigning the values in parameter list and initialiser list, which explains why this becomes valid only for the later stages of object initialization.
https://stackoverflow.com/a/64548861/ for various differences between the different ways to initialize members and for an example where the different ways matter.

What's the rationale behind not inheriting static variables, in Dart?

In Dart, if one class extends another, the extended class inherits all of the super classes non-static variables, but inherits none of its static variables.
For example
class TestUpper {
static final String up = 'super';
String upup = 10;
}
class TestLower extends TestUpper {
static final String low = 'lower';
String lowlow = 11;
}
var lower = new TestLower();
print( lower.lowlow ); // <== 11
print( lower.upup ); // <== 10
print( TestLower.low ); // <== "lower"
print( TestLower.up ); // <== No static getter 'get:up' declared in class 'TestLower'
Is this the normal behavior? If so, I would appreciate if someone explained the rationale behind it.
Yes, there's no inheritance of static members. See Static Methods section of the language specification :
Inheritance of static methods has little utility in Dart. Static methods cannot be overridden. Any required static function can be obtained from its declaring library, and there is no need to bring it into scope via inheritance. Experience shows that developers are confused by the idea of inherited methods that are not instance methods.
Of course, the entire notion of static methods is debatable, but it is retained here because so many programmers are familiar with it. Dart static methods may be seen as functions of the enclosing library.