openplanning

Property trong Dart

  1. Property là gì?
  2. Getter
  3. Setter
  4. Examples

1. Property là gì?

Trước khi đưa ra định nghĩa "Property là gì?" chúng ta cần làm rõ "Trường (field) là gì?".
Trường (field) là một biến được khai báo trực tiếp trong một lớp.
Xem thêm bài viết về constructor để hiểu cách Dart gán giá trị cho các trường:
Trong ngôn ngữ Dart, tất cả các trường của lớp đều có thể được truy cập từ bên ngoài lớp. Bạn có thể lấy ra giá trị của chúng và sét giá trị mới cho chúng, chẳng hạn như ví dụ sau:
field_ex1.dart
class Person {
  String name;
  String gender;
  String? country; // Allow null value.

  Person(this.name, this.gender, this.country); // Constructor
  Person.nameAndGender(this.name, this.gender); // Constructor

  // Method:
  void selfIntroduce() {
    if (country != null) {
      print('Hi, My name is $name, from $country');
    } else {
      print('Hi, My name is $name');
    }
  }
}

void main() {
  Person emma = new Person('Emma', 'Female', 'USA'); // Create an object
  emma.selfIntroduce(); // Call method.

  var name = emma.name; // get the value of a field

  print('emma.name: $name');
  print('emma.gender: ${emma.gender}');
  print('emma.country: ${emma.country}');

  print(' --- Set new value to country field ---: ');

  emma.country = 'Canada'; // set new value to a field
  print('emma.country: ${emma.country}');
}
Output:
Hi, My name is Emma, from USA
emma.name: Emma
emma.gender: Female
emma.country: USA
 --- Set new value to country field ---:
emma.country: Canada
Private Field?
Khác với Java, Dart không cung cấp các từ khoá private, protectedpublic. Nếu muốn có một private field bạn nên đặt tên cho trường đó bắt đầu bởi dấu gạch dưới ( _ ). Chẳng hạn _fieldName.
Các trường với tên bắt đầu bởi dấu gạch dưới ( _ ) được ngầm định là private (riêng tư), chúng được sử dụng trong nội bộ thư viện. Đó đơn thuần là một quy ước ngầm, các lập trình viên sử dụng thư viện không nên truy cập vào các trường này từ bên ngoài vì nó trái với ý tưởng thiết kế thư viện. Việc cố tình truy cập vào các trường này từ bên ngoài có thể gây ra các sai lầm ngoài mong đợi.
Property?
Về cơ bản, một khi bạn có thể tiếp cận một trường tại một nơi nào đó, bạn có thể lấy ra giá trị của nó và gán giá trị mới cho nó.
Property là một khái niệm tương tự như trường (field), nhưng nó có các tính năng đặc biệt hơn. Property được chia làm 3 loại:
  • Read-only Property: Cho phép truy cập vào giá trị của nó, nhưng không cho phép sét giá trị mới cho nó.
  • Write-only Property: Cho phép sét giá trị mới cho nó, nhưng không cho phép truy cập vào giá trị của nó.
  • Read/Write Property: Cho phép truy cập vào giá trị, và cho phép sét giá trị mới cho nó.
Theo ý tưởng thiết kế của Dart, bạn nên đặt tên cho tất cả các trường trong lớp bắt đầu bởi dấu gạch dưới ( _ ), điều này có nghĩa là chúng chỉ được sử dụng trong nội bộ thư viện, và sử dụng các property để thay thế vai trò của các trường trong việc giao tiếp với thế giới bên ngoài.

2. Getter

Cú pháp Getter cho phép bạn định nghĩa một property mà bên ngoài lớp có thể truy cập vào giá trị của nó, nhưng không thể sét giá trị mới cho nó trừ khi bạn cũng định nghĩa Setter cho property này.
data_type get property_name {
     // code ...
     return a_value;
}
Ví dụ: Lớp Person dưới đây cho phép truy cập vào giá trị của property name, nhưng không cho phép thay đổi giá trị của nó từ bên ngoài.
property_getter_ex1.dart
class Person {
  String _name; // private field
  String gender;
  String? _country; // private field

  Person(this._name, this.gender, this._country); // Constructor
  Person.nameAndGender(this._name, this.gender); // Constructor
  // Getter
  String get name {
    return _name;
  }

  // Getter
  String get country {
    return _country ?? '[Not Provided]';
  }

  // Method:
  void selfIntroduce() {
    if (_country != null) {
      print('Hi, My name is $name, from $country');
    } else {
      print('Hi, My name is $name');
    }
  }
}

void main() {
  var emma = Person.nameAndGender('Emma', 'Female'); // Create an object
  emma.selfIntroduce(); // Call method.

  var name = emma.name; // get the value of a property
  var country = emma.country; // get the value of a property
  print('emma.name: $name');
  print('emma.country: $country');

  // Can not set new value to property - name
  // emma.name = 'New Name'; // ERROR!!
}
Output:
Hi, My name is Emma
emma.name: Emma
emma.country: [Not Provided]

3. Setter

Cú pháp Setter cho phép bạn định nghĩa một property cho phép sét giá trị mới cho nó, nhưng không cho phép truy cập vào giá trị của nó trừ khi bạn cũng định nghĩa Getter cho property này.
set property_name(data_type newValue)  {
     // code
}
Ví dụ:
property_setter_ex1.dart
class Person {
  String name;
  String gender;
  String _country; // private field

  Person(this.name, this.gender, this._country); // Constructor

  // Setter
  set country(String newCountry) {
    _country = newCountry;
  }

  // Method:
  void selfIntroduce() {
    print('Hi, My name is $name, from $_country');
  }
}

void main() {
  var emma = Person('Emma', 'Female', 'USA'); // Create an object
  emma.selfIntroduce(); // Call method.

  // Set new value to country property.
  emma.country = 'Canada';
  emma.selfIntroduce();

  // Can not get the value of country property
  // var country = emma.country; // ERROR!!
}
Output:
Hi, My name is Emma, from USA
Hi, My name is Emma, from Canada

4. Examples

Ví dụ: Một property với cả hai GetterSetter:
property_gettersetter_ex1.dart
class Person {
  String name;
  String gender;
  String? _country; // private field

  Person(this.name, this.gender, this._country); // Constructor
  Person.nameAndGender(this.name, this.gender); // Constructor

  // Getter
  String get country {
    return _country ?? '[Not Provided]';
  }

  // Setter
  set country(String newCountry) {
    _country = newCountry;
  }

  // Method:
  void selfIntroduce() {
    if(_country != null)  {
        print('Hi, My name is $name, from $_country');
    } else {
      print('Hi, My name is $name');
    }
    
  }
}

void main() {
  var emma = Person.nameAndGender('Emma', 'Female'); // Create an object
  emma.selfIntroduce(); // Call method.
  var country = emma.country;
  print('Country: $country');

  print(' --- set new value to country property ---');

  emma.country = 'Canada'; // Set new value to country property.
  emma.selfIntroduce();
}
Output:
Hi, My name is Emma
emma.country: [Not Provided]
 --- set new value to country property ---
Hi, My name is Emma, from Canada