I'm sorry if this sounds like an extremely foolish question but it's really been bugging me.
What is the "this." that I see? Whenever I see the documentation in flutter I see it used in things like the following in the documentation:
this.initialRoute,
this.onGenerateRoute,
this.onGenerateInitialRoutes,
this.onUnknownRoute,
this.navigatorObservers
I'll be more than happy to also read up any links or documentation regarding it.
The 'this' keyword refers to the current instance.
You only need to use this when there is a name conflict. Otherwise, Dart style omits the this.
class Car {
String engine;
void newEngine({String engine}) {
if (engine!= null) {
this.engine= engine;
}
}
}
So you can be consistent with the name of your parameters, either in the constructor or in some function in the class.
class Car {
String engine;
void updateEngine({String someWeirdName}) {
engine = someWeirdName;
}
}
If you don't have a name conflict, you don't need to use this.
In other languages like Python and Swift, the word 'self' will do the same thing as 'this'.
Basically, this keyword is used to denotes the current instance. Check out the below example.
void main() {
Person mike = Person(21);
print(mike.height);
}
class Person {
double height;
Person(double height) {
height = height;
}
}
When we run this dart code, it outputs null as the height. Because we have used height = height inside the Person constructor, but the code doesn't know which height is the class property.
Therefore, we can use this keyword to denotes the current instance and it will help the code to understand which height belongs to the class. So, we can use it as below and we will get the correct output.
void main() {
Person mike = Person(21);
print(mike.height);
}
class Person {
double height;
Person(double height) {
this.height = height;
}
}
Use of this keyword
The this keyword is used to point the current class object.
It can be used to refer to the present class variables.
We can instantiate or invoke the current class constructor using this keyword.
We can pass this keyword as a parameter in the constructor call.
We can pass this keyword as a parameter in the method call.
It removes the ambiguity or naming conflict in the constructor or method of our instance/object.
It can be used to return the current class instance.
Related
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.
I am confused by how dart handles its class variables.
Consider the below snippet.
double income = 0.0;
printer() {
print(this.income);
print(income);
}
}
void main() {
Testing testing = Testing();
testing.printer();
}
Can someone enlighten me please.
Actually both prints 0. This is to refer to the class variable, if there is a name conflict.
Use this only when there is a name conflict. Otherwise, Dart style omits the this.
For example, I expect <T extends type> can works like this:
Class Parent {
String data;
Parent({ this.data });
}
Class Child extends Parent {
Child({ this.data }) : Parent(data: data);
void showData() { print(data); }
}
T wrapper<T extends Parent>(String value) {
var result = T(data: value);
return result;
}
void main() {
var trial = wrapper<Child>("Hello world");
trial.showMessage(); // print "Hello world"
}
But turns out it gives me error at var result = T(data: value);, saying that T is not a function. When I specified , I expect that T can be operated like Parent class, and if I supplied its descendant like Child, the operation done will be Child instead. But the constructor will work either way because T extends Parent. Is such thing possible?
Constructors are not inherited. You know that already, because you wrote one yourself in your child class that does nothing but call the base class with the same parameters.
One could as well write a different constructor. So "X extends Y" says a lot about X, but it does not say anything about how the constructor of X looks (or whether it even has a constructor accessible in that scope). So a constructor call is not in the properties available to you when you specify your generic to "extend Y", because Y can do exactly nothing to make sure all it's derivates follow a specific construction method.
Different languages deal with the problem of "but how do I construct a new instance of my generic type" in different ways, but the underlying concept is common to almost all concepts of generics where the generic code is compiled before knowing the specific types of all T's handled. A constructor is not inherited in most OOP languages, therefor it is not guaranteed to be there for any "X extends Y" even if Y has it.
It might be easy to overlook when you have all your code in one compilation unit. The compiler should be able to figure it out, right? But your code might not be in a single compilation unit:
Codebase one:
Class Parent {
String data;
Parent({ this.data });
}
T wrapper<T extends Parent>(String value) {
var result = T(data: value);
return result;
}
At this point, the compiler has no idea what "Child" might look like. It cannot possibly determine that the child class that will be used in the Future has a constructor like that.
Codebase 2:
Class Child extends Parent {
Child({ this.data }) : Parent(data: data);
void showData() { print(data); }
}
void main() {
var trial = wrapper<Child>("Hello world");
trial.showMessage(); // print "Hello world"
}
Now, at this point, a compiler could figure out that the program it's given would actually work. Some concepts of generics do that, where generics cannot be compiled into independent libraries, they always come as source code, because only the final compiler producing the executable can determine whether it would work with a specific class. Flutter does not do this. Flutter needs the generic itself be valid for the constraints given.
All newer language's versions of generics have followed the path of knowing the constraints beforehand and only allowing code operating inside those constraints. And I think it's good because while it has it's shortcomings, it leaves less room for errors or cryptic error messages.
I have a file fancy_button.dart for a custom Flutter widget FancyButton which is like:
class FancyButton extends StatefulWidget {
// ...
}
class _FancyButtonState extends State<FancyButton> {
// ...
}
// Declaration outside any class:
Map<_FancyButtonState, Color> _buttonColors = {};
final _random = Random();
int next(int min, int max) => min + _random.nextInt(max - min);
// ...
The application works just fine. Notice that I declare and use some variables outside any class. Now my question is: how is it even possible? Shouldn't everything be inside a class in Dart, like Java?
No, Dart supports variables and functions defined in global space. You can see this with the main() method which are declared outside any class.
Also, global variables (and static class variables) are lazy evaluated so the value are first defined when you are trying to use them. So your runtime are not going to slow down even if there are a bunch of global variables there are not used.
Are you coming from Java before touching Dart?
Basically, Dart is not single-class-single-file like how Java works. Yes, it does support Object Oriented Programming (in kinda different way). The behavior of constructor is different. There is no public, private, and protected keywords. Please just refer to the official docs.
Anyway, you don't need a complex public static void main(). The real entry point is main(). Unless you define that function, you won't be able to run a file in command line.
Method
method() {}
function
function func() {}
Above is just to elaborate difference between method and function.
class Student {
constructor(name, age) {
this.name = name;
this.age = age;
}
method1(){}
}
In the above class, after writing the definition.
I want to add a method2 to the class, similar to the way method1 is there.
I can add a function like soo
Student.prototype.func = function(){...}
But I do not have a way to add a method on the same class. and inside function I will not be able to use super as that is just available inside the method.
Is there a way I can add method after the class is defined ?
So that I will be able to use super inside that.
As has already been explained, you can only use super() inside the regular class definition. But, long before we had ES6, we were calling parent method implementations manually. It can be done using the parent's prototype:
class Person {
talk() {
// some implementation here
}
}
class Student extends Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
Student.prototype.talk = function(data) {
// now call base method manually
Person.prototype.talk.call(this, data);
// then do our extra work
log(data);
}
Of course, normally you could just declare all your methods within the class declaration so this would not be something you would normally need to do.
Your snippet adding a new property to the prototype is only approach for adding a function later. One main difference in this case is that simple assignment like that will create the property as enumerable by default, whereas class syntax would create is as non-enumerable. You could use
Object.defineProperty(Student.prototype, "func", {
configurable: true,
writable: true,
value: function() {
},
});
to address that at least.
Unfortunately as you've seen, adding things to the prototype afterward does not allow usage of super.foo. There is no way for this to be supported, because the behavior of super is based specifically on the lexical nesting of the method syntax method(){} being inside of the class syntax. Methods added programmatically later on would have no way to know which prototype is the "super" one.