Gus*_*ger 32 dart dart-null-safety
我正在尝试为我的类创建一个“copyWith”方法,它适用于大多数场景。
问题是当我尝试将可为 null 的属性设置为 null 时,因为我的函数无法识别它是否是有意的。
前任。:
class Person {
final String? name;
Person(this.name);
Person copyWith({String? name}) => Person(name ?? this.name);
}
void main() {
final person = Person("Gustavo");
print(person.name); // prints Gustavo
// I want the name property to be nul
final person2 = person.copyWith(name: null);
print(person2.name); // Prints Gustavo
}
Run Code Online (Sandbox Code Playgroud)
有谁知道这种情况的一些解决方法?这真的很困扰我,我不知道如何避免这种情况。
Dan*_*ndt 45
一种解决方案是使用函数来设置该值。这给你更多的选择。
null
() => null
null
() => 'Gustavo'
Gustavo
class Person {
final String? name;
Person(this.name);
Person copyWith({String? Function()? name}) =>
Person(name != null ? name() : this.name);
}
void main() {
final person = Person('Gustavo');
print(person.name); // prints Gustavo
// I want the name property to be nul
final person2 = person.copyWith(name: () => null);
print(person2.name); // Prints null
final person3 = person.copyWith(name: () => 'new name');
print(person3.name); // Prints new name
final person4 = person.copyWith();
print(person4.name); // Prints Gustavo
}
Run Code Online (Sandbox Code Playgroud)
它使设置名称稍微麻烦一些,但好的一面是,如果您尝试直接传递字符串,编译器会告诉您提供了错误的类型,因此会提醒您向其中添加() =>
。
iDe*_*ode 23
受到@jamesdlin回答的启发:
您所需要做的就是提供一个包装器。考虑这个例子:
class Person {
final String? name;
Person(this.name);
Person copyWith({Wrapped<String?>? name}) =>
Person(name != null ? name.value : this.name);
}
// This is all you need:
class Wrapped<T> {
final T value;
const Wrapped.value(this.value);
}
void main() {
final person = Person('John');
print(person.name); // Prints John
final person2 = person.copyWith();
print(person2.name); // Prints John
final person3 = person.copyWith(name: Wrapped.value('Cena'));
print(person3.name); // Prints Cena
final person4 = person.copyWith(name: Wrapped.value(null));
print(person4.name); // Prints null
}
Run Code Online (Sandbox Code Playgroud)
小智 17
有多种选择:
1.价值获取者
class B {
const B();
}
class A {
const A({
this.nonNullable = const B(),
this.nullable,
});
final B nonNullable;
final B? nullable;
A copyWith({
B? nonNullable,
ValueGetter<B?>? nullable,
}) {
return A(
nonNullable: nonNullable ?? this.nonNullable,
nullable: nullable != null ? nullable() : this.nullable,
);
}
}
const A().copyWith(nullable: () => null);
const A().copyWith(nullable: () => const B());
Run Code Online (Sandbox Code Playgroud)
2. Quiver 套件中可选
class B {
const B();
}
class A {
const A({
this.nonNullable = const B(),
this.nullable,
});
final B nonNullable;
final B? nullable;
A copyWith({
B? nonNullable,
Optional<B>? nullable,
}) {
return A(
nonNullable: nonNullable ?? this.nonNullable,
nullable: nullable != null ? nullable.value : this.nullable,
);
}
}
const A().copyWith(nullable: const Optional.fromNullable(null));
const A().copyWith(nullable: const Optional.fromNullable(B()));
Run Code Online (Sandbox Code Playgroud)
3.copyWith作为字段
class _Undefined {}
class B {
const B();
}
class A {
A({
this.nonNullable = const B(),
this.nullable,
});
final B nonNullable;
final B? nullable;
// const constructor no more avaible
late A Function({
B? nonNullable,
B? nullable,
}) copyWith = _copyWith;
A _copyWith({
B? nonNullable,
Object? nullable = _Undefined,
}) {
return A(
nonNullable: nonNullable ?? this.nonNullable,
nullable: nullable == _Undefined ? this.nullable : nullable as B?,
);
}
}
A().copyWith(nullable: null);
A().copyWith(nullable: const B());
Run Code Online (Sandbox Code Playgroud)
4.copyWith重定向构造函数
class _Undefined {}
class B {
const B();
}
abstract class A {
const factory A({
B nonNullable,
B? nullable,
}) = _A;
const A._({
required this.nonNullable,
this.nullable,
});
final B nonNullable;
final B? nullable;
A copyWith({B? nonNullable, B? nullable});
}
class _A extends A {
const _A({
B nonNullable = const B(),
B? nullable,
}) : super._(nonNullable: nonNullable, nullable: nullable);
@override
A copyWith({B? nonNullable, Object? nullable = _Undefined}) {
return _A(
nonNullable: nonNullable ?? this.nonNullable,
nullable: nullable == _Undefined ? this.nullable : nullable as B?,
);
}
}
const A().copyWith(nullable: null);
const A().copyWith(nullable: const B());
Run Code Online (Sandbox Code Playgroud)
5. copyWith重定向构造函数2
class _Undefined {}
class B {
const B();
}
abstract class A {
const factory A({
B nonNullable,
B? nullable,
}) = _A;
const A._();
B get nonNullable;
B? get nullable;
A copyWith({B? nonNullable, B? nullable});
}
class _A extends A {
const _A({
this.nonNullable = const B(),
this.nullable,
}) : super._();
@override
final B nonNullable;
@override
final B? nullable;
@override
A copyWith({B? nonNullable, Object? nullable = _Undefined}) {
return _A(
nonNullable: nonNullable ?? this.nonNullable,
nullable: nullable == _Undefined ? this.nullable : nullable as B?,
);
}
}
const A().copyWith(nullable: null);
const A().copyWith(nullable: const B());
Run Code Online (Sandbox Code Playgroud)
Person.name
被声明为不可空,因此不可能为其copyWith
分配空值。如果您想要Person.name
可为空,您应该问自己是否真的想要区分null
和 空字符串。通常你不会。
如果您确实希望同时允许null
和空字符串,那么您将需要使用其他一些哨兵值:
class Person {
static const _invalid_name = '_invalid_name_';
final String? name;
Person(this.name);
Person copyWith({String? name = _invalid_name}) =>
Person(name != _invalid_name ? name : this.name);
}
Run Code Online (Sandbox Code Playgroud)
或者您需要将其包装在另一个类中,例如:
class Optional<T> {
final bool isValid;
final T? _value;
// Cast away nullability if T is non-nullable.
T get value => _value as T;
const Optional()
: isValid = false,
_value = null;
const Optional.value(this._value) : isValid = true;
}
class Person {
final String? name;
Person(this.name);
Person copyWith({Optional<String?> name = const Optional()}) =>
Person(name.isValid ? name.value : this.name);
}
void main() {
final person = Person("Gustavo");
print(person.name);
final person2 = person.copyWith(name: Optional.value(null));
print(person2.name);
}
Run Code Online (Sandbox Code Playgroud)
有一些现有的包实现了Optional
类似的类,可能可以帮助您。
归档时间: |
|
查看次数: |
9690 次 |
最近记录: |