In Dart, the use of ?
after a type (e.g., String?
) indicates that the variable can be nullable, meaning it can either hold a non-null value of that type or be null
. On the other hand, if you declare a variable without ?
(e.g., String
), it means the variable must always contain a non-null value of that type.
在达特,使用?在一个类型(例如,String?)之后,表示变量可以为null,这意味着它可以包含该类型的非null值,也可以为null。另一方面,如果您声明一个没有?(例如,String),这意味着变量必须始终包含该类型的非null值。
In your UserModel
class, you have defined the fields as nullable:
在UserModel类中,您已经将字段定义为可以为null:
final String? username;
final int? age;
final String? phoneNumber;
This means that these fields can be assigned null
values. Whether you should use nullable or non-nullable types depends on the requirements of your application and how you want to handle null values. Here are some considerations:
这意味着可以为这些字段分配空值。您应该使用可为null还是不可为null的类型取决于应用程序的要求以及您希望如何处理null值。以下是一些注意事项:
Use nullable types (String?
, int?
, etc.) when:
- You expect that the data you receive may have missing values or nulls, and you want to represent that in your model.
- You want to distinguish between a null value and an empty string, for example.
- You want to avoid runtime null reference exceptions when accessing these fields.
Use non-nullable types (String
, int
, etc.) when:
- You expect that the data should always have a valid non-null value, and a null value would indicate a programming error or a data integrity issue.
- You want to enforce that these fields are always initialized with valid values when creating an instance of the model.
Regarding your second question about how to handle null values in the model or controller without cluttering the UI code, you can achieve this by providing default values or transforming the data when constructing the UserModel
object. Here's an example of how you can handle null values in the model constructor:
关于第二个问题,即如何在不扰乱UI代码的情况下处理模型或控制器中的null值,您可以通过提供默认值或在构造UserModel对象时转换数据来实现这一点。以下是如何在模型构造函数中处理null值的示例:
class UserModel {
final String username;
final int age;
final String phoneNumber;
UserModel({
String? username,
int? age,
String? phoneNumber,
}) : username = username ?? 'Default Username',
age = age ?? 0,
phoneNumber = phoneNumber ?? 'N/A';
@override
String toString() {
return 'Username => $username\nAge => $age\nPhone number => $phoneNumber';
}
}
In this modified UserModel
, if any of the provided values (username, age, or phoneNumber) are null
, it will default to a specified value (e.g., 'Default Username' for username) instead of allowing null values. This way, you ensure that your UserModel
always contains non-null values, which can make it easier to work with in the UI code.
在这个修改后的UserModel中,如果提供的任何值(用户名、年龄或电话号码)为null,它将默认为指定值(例如,用户名的“default username”),而不允许为null值。通过这种方式,您可以确保UserModel始终包含非null值,这可以使在UI代码中使用它更容易。
I will suggest to not include ?
operator on class property. Now, it is not mandatory/forced to follow, but, from the perspective to reduce null exception, your code must be null safe, alternatively, you should use ?
based on your need.
我建议不包括?类属性上的运算符。现在,它不是强制性的/强制遵循的,但是,从减少null异常的角度来看,您的代码必须是null安全的,或者,您应该使用?根据您的需要。
In my experience, having a class like this, is a good-to-have structure.
根据我的经验,有这样一个班,是一个很好的结构。
class UserModel {
final String username;
final int age;
final String phoneNumber;
UserModel({
required this.username,
required this.age,
required this.phoneNumber,
});
}
You can ask, what if my phoneNumber
is not required
to create a UserModel
, how will I manage that. In that case, let's **remove**
the requried
keyword from constructor
of this.phoneNumber
and assign a default value
, the default value
will only assign, if and only if, you didn't provide any phoneNumber
as argument, while creating an UserModel
object.
你可以问,如果创建UserModel不需要我的phoneNumber,我将如何管理它。在这种情况下,让我们**从this.phoneNumber的构造函数中删除**所需的关键字,并分配一个默认值,默认值将仅在创建UserModel对象时,如果且仅当您没有提供任何phoneNumber作为参数时分配。
class UserModel {
final String username;
final int age;
final String phoneNumber;
UserModel({
required this.username,
required this.age,
this.phoneNumber = "",
});
}
another way to rewrite the same thing is
重写相同内容的另一种方法是
class UserModel {
final String username;
final int age;
final String phoneNumber;
UserModel({
required this.username,
required this.age,
required String? phoneNumber,
}) : phoneNumber = phoneNumber ?? "";
}
For server data handling, I will recommend to use a factory constructor while maintaining the above structure.
对于服务器数据处理,我建议在维护上述结构的同时使用工厂构造函数。
class UserModel {
final String username;
final int age;
final String phoneNumber;
UserModel({
required this.username,
required this.age,
required this.phoneNumber,
});
factory UserModel.fromServer(Map<String, dynamic> map) {
return UserModel(
username: map["username"], // assuming username can't be null
age: map["age"], // assuming age can't be null
phoneNumber: map["phoneNumber"] ?? "", // assuming phoneNumber can be null
);
}
}
To summarize the answer, you should avoid using nullable
varialble most of the time. That doesn't imply that you shouldn't use nullable
data type at all. What if you want to check if phoneNumber
is provided or not by checking if the value is null
or not. I mean who check the data is provided or not by checking if it is empty or not (acctualy I do).
为了总结答案,您应该避免在大多数情况下使用可为null的变量。这并不意味着您根本不应该使用可为null的数据类型。如果您想通过检查值是否为null来检查是否提供了phoneNumber,该怎么办。我的意思是,谁通过检查数据是否为空来检查数据是否提供(事实上我是这样做的)。
I use nullable fields in my DTO objects, because I want them to be "as close to the metal" as I can for input/output. However, in my data domain objects (aka "business objects"), if a value is optional I prefer fpdart's Option
wrapper to guarantee that I have a sentinel when a value is deliberately absent.
我在DTO对象中使用可为null的字段,因为我希望它们在输入/输出时“尽可能接近金属”。然而,在我的数据域对象(也称为“业务对象”)中,如果一个值是可选的,我更喜欢fpdart的Option包装器,以确保在故意不存在值时我有一个sentinel。
更多回答
我是一名优秀的程序员,十分优秀!