Приватные поля и методы. Инкапсуляция

Последнее обновление: 03.04.2023

По умолчанию поля класса являются публичными. А это значит, что они доступны в любой точке программы. И мы можем свободно получить или изменить значения этих полей. Однако подобное поведение не всегда может быть желательным. Нередко бывает необходимо скрыть внутреннюю реализацию от внешнего кода, что позволит избежать некорректного использования полей, передачи им некорректных значений.

Dart позволяет сделать поля класса приватными - к таким полям можно обратиться только внутри класса. Вне класса обратиться к приватным полям нельзя. Чтобы сделать поля приватными, необходимо добавить перед их именем символ подчеркивания (_). Однако тут есть нюансы. Например, пусть весь код программы размещен в одном файле main.dart, и в этом коде определен класс Person:

class Person{

	String _name ="";   // приватное поле name
	int _age =0;        // приватное поле age
	
    Person(String name, int age) {
		
        this._name = name;
        this._age = age;
	}
	
    void display(){
        print("Name: $_name \tAge: $_age");
    }
}

void main() {

    Person tom = Person("Tom", 38);  
    tom.display();      // Name: Tom       Age: 38
    tom._age = 100500;
    tom._name = "toidi";
    tom.display();      // Name: toidi     Age: 100500
}

Здесь в классе Person поля name и age, которые представляют соответственно имя и возраст, определены как приватные:

String _name ="";   // приватное поле name
int _age =0;        // приватное поле age

Однако в функции main мы по прежнему можем обратиться к этим полям и изменить их значения:

tom._age = 100500;
tom._name = "toidi";

И консольный вывод покажет, что значения полей действителено изменились:

Name: Tom       Age: 38
Name: toidi     Age: 100500

В чем же тогда приватность? И тут надо учитывать, что приватность применяется, если класс определен в отдельной библиотеке/файле. Поэтому определим в одной папке с главным файлом новый файл person.dart:

class Person{

	String _name ="";   // приватное поле name
	int _age =0;        // приватное поле age
	
    Person(String name, int age) {
		
        this._name = name;
        this._age = age;
	}
	
    void display() => print("Name: $_name \tAge: $_age");
}

Здесь определен тот же класс Person. А в главном файле main.dart подключим этот файл и используем класс Person:

import 'person.dart';     // подключаем файл с классом Person

void main() {

    Person tom = Person("Tom", 38);  
    tom.display();      // Name: Tom       Age: 38
    // tom._age = 100500;       // Ошибка
    // tom._name = "toidi";     // Ошибка
}

С помощью директивы import подключаем файл "person.dart" и в функции main создаем объект Person. Но теперь мы уже не сможем обратиться к полям name и age (поэтому в примере выше соответствующие строки закомментированы). А если мы и попробуем это сделать, то столкнемся с ошибкой.

Стоит отметить, что то же самое обстоятельно касается определения приватных методов - если их имя начинается с подчеркивания, то они тоже являются приватными, и их нельзя вызвать вне класса:

class Person{

	String _name ="";   // приватное поле name
	int _age =0;        // приватное поле age
	
    Person(String name, int age) {
		
        this._name = name;
        this._age = age;
	}
    void _printPerson() => print("Name: $_name \tAge: $_age");
    void display() =>_printPerson();
}

В данном случае метод _printPerson является приватным, и вне текущего файла к нему обратиться нельзя.

Приватные конструкторы

Также могут быть приватными именованные конструкторы. Например:

class Person{

	String _name;   // приватное поле name
	int _age;        // приватное поле age
	
    Person(String name, int age): this._create(name, age);  // вызываем приватный конструктор

    Person._create(this._name, this._age);    // приватный конструктор
    void display() => print("Name: $_name \tAge: $_age");
}

Здесь конструктор Person._create() определен как приватный - для этого перед именем конструктора также ставится символ подчеркивания. Этот консструктор устанавливает значения приватных переменных:

Person._create(this._name, this._age);

Внутри класса мы можем вызвать этот конструктор

Person(String name, int age): this._create(name, age);

Вне файла данного класса приватный конструктор не доступен.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850