Non-nullable (secara default)
Eksperimen yang tidak dapat dibatalkan (secara default) saat ini dapat ditemukan di nullsafety.dartpad.dev .
Ingatlah bahwa Anda dapat membaca spesifikasi lengkap di sini dan peta jalan lengkap di sini .
Apa yang dimaksud dengan non-nullable secara default?
void main() {
String word;
print(word); // illegal
word = 'Hello, ';
print(word); // legal
}
Seperti yang Anda lihat di atas, variabel yang tidak dapat dibatalkan secara default berarti bahwa setiap variabel yang dideklarasikan secara normal tidak dapat null
. Akibatnya, setiap operasi yang mengakses variabel sebelum ditugaskan adalah ilegal.
Selain itu, penetapan null
ke variabel yang tidak dapat dibatalkan juga tidak diizinkan:
void main() {
String word;
word = null; // forbidden
world = 'World!'; // allowed
}
Bagaimana ini membantu saya?
Jika suatu variabel tidak dapat dibatalkan , Anda dapat memastikan bahwa itu tidak pernah null
. Karena itu, Anda tidak perlu memeriksanya sebelumnya.
int number = 4;
void main() {
if (number == null) return; // redundant
int sum = number + 2; // allowed because number is also non-nullable
}
Ingat
Bidang instance dalam kelas harus diinisialisasi jika tidak dapat dibatalkan:
class Foo {
String word; // forbidden
String sentence = 'Hello, World!'; // allowed
}
Lihat di late
bawah untuk mengubah perilaku ini.
Jenis tidak dapat dihapus ( ?
)
Anda dapat menggunakan jenis yang dapat dibatalkan dengan menambahkan tanda tanya ?
ke jenis variabel:
class Foo {
String word; // forbidden
String? sentence; // allowed
}
Sebuah nullable variabel tidak perlu diinisialisasi sebelum dapat digunakan. Ini diinisialisasi sebagai null
default:
void main() {
String? word;
print(word); // prints null
}
!
Menambahkan !
untuk setiap variabel e
akan melempar kesalahan runtime jika e
null dan sebaliknya mengubahnya menjadi non-nullable nilai v
.
void main() {
int? e = 5;
int v = e!; // v is non-nullable; would throw an error if e were null
String? word;
print(word!); // throws runtime error if word is null
print(null!); // throws runtime error
}
late
Kata kunci late
dapat digunakan untuk menandai variabel yang akan diinisialisasi nanti , yaitu tidak ketika mereka dideklarasikan tetapi ketika mereka diakses. Ini juga berarti bahwa kita dapat memiliki bidang instance yang tidak dapat dibatalkan yang diinisialisasi nanti:
class ExampleState extends State {
late String word; // non-nullable
@override
void initState() {
super.initState();
// print(word) here would throw a runtime error
word = 'Hello';
}
}
Mengakses word
sebelum diinisialisasi akan menimbulkan kesalahan runtime.
late final
Variabel akhir sekarang juga dapat ditandai terlambat:
late final int x = heavyComputation();
Di sini heavyComputation
hanya akan disebut sekali x
diakses. Selain itu, Anda juga dapat mendeklarasikan late final
tanpa penginisialisasi, yang sama dengan hanya memiliki late
variabel, tetapi hanya dapat ditugaskan satu kali.
late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden
Perhatikan bahwa semua variabel tingkat atas atau statis dengan penginisialisasi sekarang akan dievaluasi late
, tidak peduli apakah itu variabel final
.
required
Dahulu anotasi ( @required
), sekarang sudah ada sebagai modifier. Ini memungkinkan untuk menandai parameter apa pun yang dinamai (untuk fungsi atau kelas) sebagai required
, yang membuatnya tidak dapat dibatalkan:
void allowed({required String word}) => null;
Ini juga berarti bahwa jika suatu parameter tidak dapat dibatalkan , parameter tersebut harus ditandai sebagai required
atau memiliki nilai default:
void allowed({String word = 'World'}) => null;
void forbidden({int x}) // compile-time error because x can be null (unassigned)
=>
null;
Parameter bernama lainnya harus nullable :
void baz({int? x}) => null;
?[]
Operator nol sadar ?[]
telah ditambahkan untuk operator indeks []
:
void main() {
List<int>? list = [1, 2, 3];
int? x = list?[0]; // 1
}
Lihat juga artikel ini tentang keputusan sintaksis .
?..
Operator cascade kini juga memiliki operator menyadari nol baru: ?..
.
Ini menyebabkan operasi kaskade berikut hanya dijalankan jika penerima tidak nol . Oleh karena itu, ?..
harus menjadi operator kaskade pertama dalam urutan kaskade:
void main() {
Path? path;
// Will not do anything if path is null.
path
?..moveTo(3, 4)
..lineTo(4, 3);
// This is a noop.
(null as List)
?..add(4)
..add(2)
..add(0);
}
Never
Untuk menghindari kebingungan: ini bukan sesuatu yang harus dikhawatirkan oleh pengembang. Saya ingin menyebutkannya demi kelengkapan.
Never
akan menjadi tipe seperti yang sudah ada sebelumnya Null
( tidaknull
) didefinisikan dalam dart:core
. Kedua kelas ini tidak dapat diperpanjang, diimplementasikan, atau dicampur, sehingga tidak dimaksudkan untuk digunakan.
Pada dasarnya, Never
berarti tidak ada tipe yang diizinkan dan Never
itu sendiri tidak dapat dipakai.
Tidak ada Never
yang List<Never>
memuaskan batasan tipe generik dari daftar, yang berarti harus kosong . List<Null>
Namun, dapat mengandung null
:
// Only valid state: []
final neverList = <Never>[
// Any value but Never here will be an error.
5, // error
null, // error
Never, // not a value (compile-time error)
];
// Can contain null: [null]
final nullList = <Null>[
// Any value but Null will be an error.
5, // error
null, // allowed
Never, // not a value (compile-time error)
Null, // not a value (compile-time error)
];
Contoh: kompiler akan menyimpulkan List<Never>
untuk kosong const List<T>
.
Never
tidak seharusnya digunakan oleh programmer sejauh yang saya ketahui.
Never
dapat digunakan?late final
pada variabel anggota atau instance hanya memeriksa saat runtime. Tidak mungkin memeriksa itu pada waktu pengembangan atau waktu kompilasi karena masalah penghentian. Jadi Anda tidak akan mendapatkan bantuan IDE dengan itu.