Кроме обычных методов и полей класс может иметь статические поля и методы. Статические поля и методы относятся ко всему классу в целом, а не к отдельным объектам. Для определения статических полей и методов перед их объявлением указывается ключевое слово static.
Статические поля хранят состояние всего класса. Статическое поле определяется как и обычное, только впереди ставится ключевое слово static. Например, рассмотрим класс Employee, который представляет работника:
class Employee{ String name; int age; static int retirementAge = 60; // статическое поле Employee(this.name, this.age); checkAge(){ if(age >= retirementAge){ print("Пора на пенсию"); } else{ print("До пенсии еще ${retirementAge - age} лет"); } } } void main (){ Employee bob = Employee("Bob", 55); bob.checkAge(); Employee.retirementAge = 65; // меняем значение статического поля bob.checkAge(); }
В классе работника определены поля для хранения имени и возраста - у каждого отдельного работника может быть свое имя и свой возраст. Кроме того, определено статическое поле для хранения пенсионного возраста retirementAge. Оно относится не к конкретному работнику, а ко всем работникам, то есть ко всему классу Employee в целом, так как нельзя для каждого отдельного работника установить свою пенсионную группу. Затем в самом классе мы можем использовать это поле как и любые другие.
Если мы хотим обратиться к этому полю вне класса, например, изменить его значение, то для обращения применяется имя класса:
Employee.retirementAge = 65;
В чем преимущества статических полей и методов перед нестатическими? Статические поля и методы потребляют меньше памяти, чем нестатические. Нестатическая переменная после инициализации (при первом присвоении значения) сразу начинает потреблять память независимо от того, используется она или нет. А статические поля и методы не инициализируются до того момента, пока они не начнут использоваться в программе. Соответственно потреблять память они начинают только тогда, когда непосредственно начинают использоваться.
Если пенсионный возраст менять не планируется, то мы можем определить как статическую константу:
class Employee{ String name; int age; static const int retirementAge = 65; Employee(this.name, this.age); checkAge(){ if(age >= retirementAge){ print("Пора на пенсию"); } else{ print("До пенсии еще ${retirementAge - age} лет"); } } } void main (){ Employee bob = Employee("Bob", 55); bob.checkAge(); print("Retirenment age: ${Employee.retirementAge}"); }
Для определения статической константы применяется выражение static const
:
static const int retirementAge = 65;
Соответственно далее в программе мы не можем изменить ее значение.
Статические методы также относятся ко всему классу и предваряются ключевым словом static
. Как правило, статические методы выполняют такие вычисления,
которые не затрагивают состояние или поведение объекта:
void main (){ int a = Operation.sum(3, 5); int b = Operation.subtract(15, 7); int c = Operation.multiply(3, 5); print("a=$a b=$b c=$c"); // a=8 b=8 c=15 } class Operation{ static int sum(int x, int y) => x + y; static int subtract(int x, int y) => x - y; static int multiply(int x, int y) => x * y; }
В данном случае для методов sum, subtract, multiply не имеет значения, какой именно экземпляр класса Operation используется. Эти методы работают только с параметрами, не затрагивая состояние класса. Поэтому их можно определить как статические.
Статические методы могут использоваться для управления доступом к статическим приватным полям, то есть состоянием, которое относится ко всему классу. В то же время в статических методах мы не можем использовать нестатические методы и поля класса. Например, пусть у нас есть следующий класс Person, который размещен в файле person.dart:
class Person{ String _name; int _id = 0; static int _count = 0; Person(this._name){ _count += 1; _id = _count; } void display(){ print("Id: $_id \tName: $_name"); } // статический метод static int getCount() => _count; }
В данном случае в классе Person определены три приватных поля. Два поля нестатические - _name и _id, который представляют соответственно имя и уникальный идентификатор человека. И одно поле статическое - count - оно будет хранить количество созданных объектов Person. Это количество относится ко всему классу в целом, не зависит от конкретного объекта, поэтому определенно как статическое.
В конструкторе при создании объекта мы увеличиваем значение count на 1 и присваиваем это значение полю _id. Таким образом, у каждого объекта Person будет уникальный числовой идентификатор.
И также в классе определен статический метод getCount, который возвращает значение статической переменной count. Таким образом, благодаря приватности поля мы не можем изменить произвольным образом его значение. И в то же время благодаря методу getCount мы можем получить его значение.
Далее в программе мы можем использовать этот статический метод, чтобы получить количество созданных объектов
import 'person.dart'; // подключаем файл с классом Person void main (){ Person tom = Person("Tom"); Person bob = Person("Bob"); Person sam = Person("Sam"); tom.display(); bob.display(); sam.display(); // получаем количество созданных объектов Person int personCount = Person.getCount(); print("Person count: $personCount"); }
Консольный вывод программы
Id: 1 Name: Tom Id: 2 Name: Bob Id: 3 Name: Sam Person count: 3
Также можно определять статические свойства - статические геттеры и сеттеры. Так, в предыдущем примере вместо статического метода мы также могли бы использовать статический геттер. Статические геттеры и сеттеры определяются аналогично нестатическим, только перед их определением указывается слово static:
class Person{ String _name; int _id = 0; static int _count = 0; Person(this._name){ _count += 1; _id = _count; } void display(){ print("Id: $_id \tName: $_name"); } // статический геттер static int get count => _count; }
Для обращения к статическим геттерам/сеттерам применяется имя класса:
import 'person.dart'; // подключаем класс Person void main (){ Person tom = Person("Tom"); Person bob = Person("Bob"); Person sam = Person("Sam"); tom.display(); bob.display(); sam.display(); // обращаемся к статическому геттеру int personCount = Person.count; print("Person count: $personCount"); }