I am new to dart and I have some basicaly question to the language itself.
During the last days I started with classes in dart.
Now I have a short question about how to declare a class correct.
void main() {
Book harryPotter =
Book(title: "Goblet of Fire", author: "J. K. Rolling", pageCount: 300);
print(harryPotter._title); // 1 -> print "A" to the console
print(harryPotter._author); // 2 -> LateInitializationError: Field '_author#18448617' has not been initialized.
}
class Book {
String _title = "A";
late String _author;
late int _pageCount;
Book(
{required String title,
required String author,
required int pageCount}); // 3
}
Why can I access to the variable even if it's set to private?
Why does the late keyword throw an error, the variable is set during the constructor call?
Do I need to write in the constructor "Book({required String this.title});", or "Book({required String title});" like in the example? If it doesn't matter, why?
Thanks for helping!
Benjamin
Your constructor is not initializing the variables!
It should be:
Book({required String title, required String author, required int pageCount})
: _title = title,
_author = author,
_pageCount = pageCount;
Without that, the _author field is not set at all, and reading an unset late field is an error.
You can't use this.something because the fields have private names (_author) and named parameters cannot have private names. Otherwise that would have been the correct approach. Instead you need to have public-named parameters and then use the value to initialize the field in an initializer list.
With that change, the fields also don't need to be late and can instead be final:
class Book {
final String _title;
final String _author;
final int _pageCount;
Book({required String title, required String author, required int pageCount})
: _title = title,
_author = author,
_pageCount = pageCount;
}
You can access the private variables from inside the same library because Dart privacy is library based.
Related
As stated in the title
Look at this code Example:
void main() {
final Student student = Student('Lincoln', 29);
print('Student before $student');
final Student newStudent = student;
newStudent?.name = 'Abraham';
print('new Student $newStudent'); /// 'Abraham', 29
print('Student after $student'); /// 'Abraham', 29 - but I need this output still 'Lincoln', 29
}
class Student {
Student(this.name, this.age);
String? name;
int? age;
#override
String toString() => '$name, $age';
}
From the code above if we set newStudent and make changes, the student variable also follows the changes, but I don't want the student variable changed. How to solve this?
You should make a new Student instance for the new one. If you want it to have the same name as age as the old you could do this for example:
final Student newStudent = Student(student.name, student.age);
and also study this example..this will clear the concept...
final List<int> numbers=[1,2,3];
print(numbers);
final List<int> numbers2=numbers;
numbers2.add(100);//this will add also to numbers
print(numbers);
//so use following for keep original array as it was
final List<int> numbers3=[...numbers];//user this spread operator
numbers3.add(200);
print(numbers);
so what u have to focus is
we passing reference not value by this statement
Student newstudent=&student (like in C language, here & sign is not used in dart
I have a model like this code
class Folder {
int id;
String title;
Color? color;
List<Note> notes;
final user = ToOne<User>();
String? get dbNotes => json.encode(notes);
set dbNotes(String? value) {
notes = json.decode(value!);
}
// ...
}
and I have this error
Cannot use the default constructor of 'Folder': don't know how to initialize param notes - no such property.
How can I convert my List<Object> to store in ObjectBox?
You can define a Note entity and create a To-One relation to the Folder class just like you did with Folder -> User.
Please do this:
you define a default constructor and initialize the variable notes
Folder(){ notes = <Notes>[]; }
In Dart, is it possible for a constructor to cancel object creation and return a different object instead?
Use case:
Users contains a static map that maps ids to User objects.
When a User is initialized, I want the User constructor to check if User with id is already created, if so: return existing User object, else create a new User object
Example (of-course not working):
class Users {
static const Map<String, User> users = {};
}
class User {
final String id;
final String firstName;
User({required id, required firstName}) {
// If user with id already exists, return that object
if (Users.users.containsKey(id) {
return Users.users[id];
}
// Else, initialize object and save it in Users.users
this.id = id;
this.firstName = firstName;
Users.users[id] = this;
}
}
Question: IS there any way to get the above pseudo code to work?
As mentioned by jamesdlin you should use a factory constructor. Here's what is mentioned in the documentation:
Use the factory keyword when implementing a constructor that doesn’t
always create a new instance of its class.
And in your case this is exactly what you want. Now here's a code sample that does what you want:
Code sample
class Users {
// Also your Map cannot be const if you want to edit it.
static Map<String, User> users = {};
}
class User {
final String id;
final String firstName;
/// Base private constructor required to create the User object.
User._({required this.id, required this.firstName});
/// Factory used to create a new User if the id is available otherwise return the User
/// associated with the id.
factory User({required String id, required String firstName}) {
// If user with id already exists, return that object
if (Users.users.containsKey(id)) {
// Force casting as non nullable as we already checked that the key exists
return Users.users[id]!;
}
// Else, initialize object and save it in Users.users
final newUser = User._(id: id, firstName: firstName);
Users.users[id] = newUser;
return newUser;
}
}
Try the full code on DartPad
You can create a function in class to handle things you want. Here's what you can implement.
class Player {
final String name;
final String color;
Player(this.name, this.color);
Player.fromPlayer(Player another) :
color = another.color,
name = another.name;
}
If this is for caching purposes or you are not creating multiple instances of the Users class, I would suggest using a pattern where static is responsible for a list of class instances. Sometimes this helps to significantly reduce the amount of code:
class User {
static final Map<String, User> users = {};
final String id, firstName;
User._({required this.id, required this.firstName});
factory User({required String id, required String firstName}) => users[id] ??= User._(id: id, firstName: firstName);
}
My Code
class Book {
String title;
String author;
int numOfPages;
Book(String title, String author, int pages) {
this.title = title;
this.author = author;
this.numOfPages = pages;
}
}
void main() {
Book bk = Book("Modern Operating Systems", "S.Tannabeaum", 1250);
print(bk.title);
}
Hey, I'm pretty a newbie to dart and programming. Here actually I wanted to make a class and it's constructor and three instances within it. And when I wanted to make an object from this class, I caught up with this error!
My code's error message!
I think something is wrong with my code, any help would be appreciable:)
There are two problems in your code. First, constructors in Dart has two "phases" where you first initialize the object and then runs the constructor body before returning the object to the caller of the constructor.
That means that you are here creating a Book object first without setting the three variables. Yes, you are setting these variables later in the constructor body but at that time it is too late.
The next problem is that if you are not setting value for a variable in Dart it will always default to the value null. With Dart 2.12, we got non-nullable types by default (NNBD) which mean all types in Dart does not allow the value null unless specified. You specify the validity of the null value by typing a ? after the name of the type. E.g. String? allows a variable to point to a String object, or null.
In this case, we don't need to specify nullable types since the problem is mostly you need to move the initialization of the variables from the constructor body in to initialization phase of the object like this:
class Book {
String title;
String author;
int numOfPages;
Book(String title, String author, int pages)
: this.title = title,
this.author = author,
this.numOfPages = pages;
}
The same can be rewritten as the following which is also the recommended way to do it:
class Book {
String title;
String author;
int numOfPages;
Book(this.title, this.author, this.numOfPages);
}
Since we are here just directly referring to each field we want to give a value. Dart will then automatically assign the values with the parameters from the constructor.
If your constructor takes a lot of arguments, it might be more readable to use named arguments. The required keyword here means that we most provide a given named parameter. If not specified, the named argument is optional (which means we most provide a default value or allow null for our parameter to be valid):
class Book {
String title;
String author;
int numOfPages;
Book({
required this.title,
required this.author,
required this.numOfPages,
});
}
void main() {
final book = Book(
title: "Modern Operating Systems",
author: "S.Tannabeaum",
numOfPages: 1250,
);
print(book.title); // Modern Operating Systems
}
I am very new to flutter and dart and trying to use singleton instance for global state(?).
which is company info that gets from backend server.
When flutter app starts, send request to the server and get a response and build a singleton instance based on the response.
So I created class
class Company {
static final Company _instance = new Company._internal();
factory Company() {
return _instance;
}
#protected
String name;
#protected
String intro;
String get companyName => name;
String get companyIntro => intro;
void setCompany(String name, String intro) {
name = name;
intro = intro;
}
Company._internal();
}
in main.dart
// companyResult is the response from server
final String companyName = companyResult["name"];
final String companyIntro = companyResult["intro"];
// create singleton instance
var company = Company();
// set company info
company.setCompany(companyName, companyIntro);
// cheking
print(company.companyName)
prints null
What am I doing wrong?
Singletons are better avoided, I would recommend that you use Provider instead and inject a simple object reference on your widget tree, so you can grab that reference whenever you want.
The reason your example prints null is because you are wrongly referencing your variables on setCompany(), the variables name and intro are all the same variable, you are changing the variables internal to the function, not the class variables, in order to fix it change it to:
void setCompany(String name, String intro) {
this.name = name;
this.intro = intro;
}
Also, I would suggest you name your variables _name and _intro, as there's no sense in having a get for a variable that's no private.