Статические методы и поля
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 20 из 110.
Теперь, когда вы понимаете разницу между членами экземпляра и статическими членами, давайте изучим, как эффективно использовать статические методы и поля. Статические члены идеально подходят для функциональности, которая относится к самой концепции класса, а не к отдельным объектам.
Статические поля хранят данные, общие для всех экземпляров. Типичные варианты использования включают счетчики, значения конфигурации или кэшированные данные:
class MathHelper {
static const double pi = 3.14159;
static int calculationCount = 0;
static double circleArea(double radius) {
calculationCount++;
return pi * radius * radius;
}
}
print(MathHelper.circleArea(5)); // 78.53975
print(MathHelper.circleArea(3)); // 28.27431
print(MathHelper.calculationCount); // 2Обратите внимание, что вы вызываете статические методы непосредственно через имя класса, а не через экземпляр. Класс MathHelper работает как утилита — вам никогда не нужно создавать объект MathHelper.
Важное правило: статические методы не могут напрямую обращаться к членам экземпляра. Они не имеют доступа к this, потому что они не привязаны к какому-либо конкретному объекту:
class Counter {
int value = 0; // Поле экземпляра
static int total = 0; // Статическое поле
void increment() {
value++; // OK — метод экземпляра обращается к полю экземпляра
total++; // OK — метод экземпляра может обращаться к статическому полю
}
static void reset() {
total = 0; // OK — статический метод обращается к статическому полю
// value = 0; // Ошибка! Невозможно обратиться к полю экземпляра
}
}Используйте статические члены, когда функциональность не зависит от состояния объекта — утилитарные функции, отслеживание фабрик или общие константы являются идеальными кандидатами.
Задание
ЛегкоДавайте создадим утилитарный класс для строковых операций, который демонстрирует, как статические методы и поля работают вместе, обеспечивая полезную функциональность без необходимости создания объектов.
Вы создадите два файла для организации вашего кода:
string_utils.dart: Определите классStringUtils, который служит вспомогательной утилитой. Ваш класс должен иметь:static const String defaultSeparator, установленный в'-'static int operationCount, начинающийся с0, для отслеживания количества выполненных операций- Статический метод
reverse(String text), который увеличиваетoperationCountи возвращает перевернутую строку - Статический метод
join(String first, String second), который увеличиваетoperationCountи возвращает две строки, соединенные черезdefaultSeparator - Статический метод
countVowels(String text), который увеличиваетoperationCountи возвращает количество гласных (a, e, i, o, u — без учета регистра) - Статический метод
getStats(), который возвращает строку, показывающую общее количество выполненных операций
main.dart: Импортируйте ваш утилитарный класс и используйте его статические методы:- Вызовите
reverse()с аргументом'hello'и выведите результат - Вызовите
join()с аргументами'dart'и'lang'и выведите результат - Вызовите
countVowels()с аргументом'Programming'и выведитеVowels: [count] - Выведите статистику, используя
getStats()
- Вызовите
Не забудьте вызывать все методы непосредственно через имя класса, так как они статические — вам не нужно создавать объекты StringUtils.
Метод getStats() должен возвращать данные в таком формате:
Operations performed: [operationCount]Ожидаемый вывод:
olleh
dart-lang
Vowels: 3
Operations performed: 3Шпаргалка
Статические члены принадлежат самому классу, а не отдельным экземплярам. Обращайтесь к ним, используя имя класса, а не объект.
Статические поля хранят данные, общие для всех экземпляров:
class MathHelper {
static const double pi = 3.14159;
static int calculationCount = 0;
static double circleArea(double radius) {
calculationCount++;
return pi * radius * radius;
}
}
print(MathHelper.circleArea(5)); // 78.53975
print(MathHelper.calculationCount); // 1Правила доступа:
- Методы экземпляра могут обращаться как к членам экземпляра, так и к статическим членам
- Статические методы могут обращаться только к статическим членам (нет доступа к
this)
class Counter {
int value = 0; // Поле экземпляра
static int total = 0; // Статическое поле
void increment() {
value++; // OK - метод экземпляра обращается к полю экземпляра
total++; // OK - метод экземпляра может обращаться к статическому полю
}
static void reset() {
total = 0; // OK - статический метод обращается к статическому полю
// value = 0; // Ошибка! Невозможно обратиться к полю экземпляра
}
}Используйте статические члены для вспомогательных функций, общих констант, счетчиков или функциональности, которая не зависит от состояния объекта.
Попробуйте сами
import 'string_utils.dart';
void main() {
// TODO: Вызовите reverse() с 'hello' и выведите результат
// TODO: Вызовите join() с 'dart' и 'lang' и выведите результат
// TODO: Вызовите countVowels() с 'Programming' и выведите "Vowels: [count]"
// TODO: Выведите статистику, используя getStats()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий