Методы в Dart
1. Что такое метод?
В языке программирования Dart метод представляет собой блок кода (block of code), который определен внутри класса и запускается только при вызове. Методы разделяют большую задачу на мелкие части и выполняют определенную операцию программы. Этот процесс повышает возможность повторного использования кода и расширяет модульный подход программы.
В основном методы делятся на 3 типа:
- Регулярный метод (нестатический и неабстрактный).
- Статический метод (static method).
- Абстрактный метод (abstract method).
2. Регулярный метод
Синтаксис для определения регулярного метода:
return_type method_name(arguments) {
// statement(s)
}
- return_type: Возвращаемый тип данных метода. Используйте ключевое слово void в качестве типа возвращаемого значения, если метод ничего не возвращает.
- method_name: Имя метода. В отличие от других языков, таких как Java, Dart не допускает двух методов с одинаковым именем, даже если они имеют разные параметры. Это необходимо для преобразования кода Dart в JavaScript.
- arguments: Параметры метода.
Например: класс Cat и его метод sayHello(..). Чтобы вызвать sayHello(..), необходимо создать объект Cat и вызвать метод, используя точечную нотацию (dot notation).
method_ex1.dart
class Cat {
void sayHello(String name) {
print("Hello $name");
}
}
void main() {
Cat tom = new Cat(); // Create a Cat object.
tom.sayHello("Jerry"); // Call the method through the object.
}
Output:
Hello Jerry
Метод может содержать 0, 1 или более параметров, разделенных запятыми.
method_ex2.dart
class Rectangle {
int width;
int height;
Rectangle(this.width, this.height); // Constructor
int getArea() {
return width * height;
}
void changeWidthHeight(int newWidth, int newHeight) {
width = newWidth;
height = newHeight;
}
void showMe() {
print('I am a rectangle, width: $width, height: $height');
}
}
void main() {
Rectangle rec = Rectangle(5, 10); // Create an object.
rec.showMe(); // Call the method.
var area = rec.getArea(); // Call the method.
print('Area: $area');
print(' --- Change width and height --- ');
rec.changeWidthHeight(25, 15); // Set newWidth, newHeight
rec.showMe(); // Call the method.
area = rec.getArea(); // Call the method.
print('Area: $area');
}
Output:
I am a rectangle, width: 5, height: 10
Area: 50
--- Change width and height ---
I am a rectangle, width: 25, height: 15
Area: 375
3. Статический метод
Dart использует ключевое слово static и синтаксис определения обычного метода для определения статического метода.
Синтаксис для определения статического метода:
static return_type method_name(arguments) {
// statement(s)
}
Характеристики статического метода:
- Статический метод вызывается через имя класса и точечную нотацию. Например, MyUtility.sum(100, 50). Имя класса и точечная нотация могут быть опущены, если вы вызываете статический метод внутренне.
- Нестатические члены класса не могут отображаться в статическом методе, если к ним не осуществляется доступ через объект (см. Пример ниже).
method_static_ex1.dart
class MyUtility {
static int sum(int a, int b) {
return a + b;
}
static int minus(int a, int b) {
return a - b;
}
}
void main() {
var result = MyUtility.sum(100, 50);
print('Sum Result: $result');
result = MyUtility.minus(100, 50);
print('Minus Result: $result');
}
Output:
Sum Result: 150
Minus Result: 50
Затем посмотрите на приведенный ниже пример:
- side1, side2 и side3 являются нестатическими полями (field) класса Triangle, которые не могут отображаться в статическом методе.
- Для вызова статического метода в определенном классе может не потребоваться имя класса и точечная нотация.
method_static_ex2.dart
class Triangle {
late double side1;
late double side2;
late double side3;
static const String DEFAULT_COLOR = 'blue'; // Static field
Triangle(double s1, double s2, double s3) {
bool valid = isValidSides(s1, s2, s3); // Check if all sides are valid.
if(!valid) {
throw ArgumentError('Invalid Sides!'); // Throw an Error.
}
side1 = s1;
side2 = s2;
side3 = s3;
}
static bool isValidSides(double s1, double s2, double s3) {
if(s1 < 0 || s2 < 0 || s3 < 0) {
return false;
}
return s1 + s2 > s3 && s1 + s3 > s2 && s2 + s3 > s1;
}
bool isEquilateralTriangle() {
return side1 == side2 && side2 == side3;
}
}
void main() {
bool valid = Triangle.isValidSides(6, 8, 10);
print('Are sides 6, 8 and 10 valid to make a triangle? $valid');
var triangle = Triangle(3.0, 4.0, 5.0);
// Check if the triangle is equilateral triangle.
var check = triangle.isEquilateralTriangle();
print('Is Equilateral Triangle? $check');
}
Output:
Are sides 6, 8 and 10 valid to make a triangle? true
Is Equilateral Triangle? false
- Exceptions
- Свойства в Dart
4. Абстрактный метод
В языке Dart абстрактный метод является нестатическим методом и не имеет тела (body).
abstract return_type method_name(arguments);
Класс с хотя бы одним абстрактным методом должен быть объявлен абстрактным. Один из его подклассов переопределит (override) абстрактные методы и напишет для них контент.
Например: Класс Person ниже должен быть объявлен как абстрактный класс, потому что он имеет по крайней мере один абстрактный метод.
method_abstract_ex1.dart
abstract class Person {
void sayHello(); // An abstract method.
}
class EnglishPerson extends Person {
void sayHello() {
print("Hello");
}
}
class RussianPerson extends Person {
void sayHello() {
print("Привет");
}
}
void main() {
Person enPerson = EnglishPerson();
enPerson.sayHello();
Person ruPerson = RussianPerson();
ruPerson.sayHello();
}
Output:
Hello
Привет
- Dart Classes
5. Дополнительные параметры
Как упоминалось выше, классы в Dart и JavaScript не поддерживают методы с одинаковыми именами, но метод может включать необязательные параметры.
Синтаксис:
// Non-static method with optional arguments:
return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]){
// statement(s)
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]){
// statement(s)
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]);
Или синтаксис - Необязательные параметры со значениями по умолчанию:
// Non-static method with optional arguments:
return_type method_name(typeM argM, typeN argN,
[typeP? argP = defaultValueP, typeQ? argQ]){
// statement(s)
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,
[typeP? argP = defaultValueP, typeQ? argQ]){
// statement(s)
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,
[typeP? argP = defaultValueP, typeQ? argQ]);
Например:
method_optional_args_ex1.dart
class MyUtility {
static String concat(String s1, String s2, [String? s3]) {
if (s3 != null) {
return s1 + s2 + s3;
}
return s1 + s2;
}
static double sum(double v1, double v2, [double? v3, double? v4]) {
return v1 + v2 + (v3 ?? 0) + (v4 ?? 0);
}
}
void main() {
String result1 = MyUtility.concat('One', 'Two');
print('result1: $result1');
String result2 = MyUtility.concat('One', 'Two', 'Three');
print('result2: $result2');
double value1 = MyUtility.sum(1, 2, 3, 4);
print('value1: $value1');
double value2 = MyUtility.sum(1, 2, 3);
print('value2: $value2');
double value3 = MyUtility.sum(1, 2);
print('value3: $value3');
}
Output:
result1: OneTwo
result2: OneTwoThree
value1: 10.0
value2: 6.0
value3: 3.0
Например:
method_optional_args_ex2.dart
class Team {
List<String> members = [];
void addMembers(String member1, [String? member2, String? member3]) {
members.add(member1);
if(member2!= null) {
members.add(member2);
}
if(member3!= null) {
members.add(member3);
}
}
void printAllMembers() {
print(' --- All members: --- ');
for(var member in members) {
print(member);
}
}
}
void main() {
var team = Team(); // Create Team object.
team.addMembers('Tom', 'Jerry');
team.printAllMembers();
}
Output:
--- All members: ---
Tom
Jerry
6. Опциональные мменованные параметры
Опциональные именованные параметры (Optional Named Parameters) - это параметры, заключенные в фигурные скобки {} и являющиеся последними параметрами в списке параметров. Все эти параметры имеют значения по умолчанию.
Синтаксис:
// Non-static method with optional named parameters:
return_type method_name(typeM argM, typeN argN,
{typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ}){
// statement(s)
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,
{typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ}){
// statement(s)
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,
{typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ});
Например:
method_optional_named_args_ex1.dart
class StringUtility {
static String concatAndTrim(String s1, String s2, {bool trimLeft = true, bool trimRight = true}) {
var s = s1 + s2;
if (trimLeft && trimRight) {
return s.trim();
} else if (trimLeft) {
return s.trimLeft();
} else if (trimRight) {
return s.trimRight();
}
return s;
}
}
void main() {
var s1 = ' One ';
var s2 = ' Two ';
var result1 = StringUtility.concatAndTrim(s1, s2); // trim left and right
print('result1: -->$result1<-- (Trim left and right)');
var result2 = StringUtility.concatAndTrim(s1, s2, trimLeft: false); // trim right only
print('result2: -->$result2<-- (Trim right only)');
var result3 = StringUtility.concatAndTrim(s1, s2, trimRight: false); // trim left only
print('result3: -->$result3<-- (Trim left only)' );
var result4 = StringUtility.concatAndTrim(s1, s2, trimLeft: false, trimRight: false); // no trim
print('result4: -->$result4<!-- (No Trim)');
}
Output:
result1: -->One Two<-- (Trim left and right)
result2: --> One Two<-- (Trim right only)
result3: -->One Two <-- (Trim left only)
result4: --> One Two <!-- (No Trim)
7. Переопределение метода
Подкласс может переопределять (override) метод родительского класса, если выполняются следующие условия:
- Два метода должны иметь одинаковое имя и одинаковые параметры.
- Тип возвращаемого значения двух методов должен быть одинаковым или тип возвращаемого значения метода в подклассе должен быть подтипом типа возвращаемого значения метода в родительском классе.
Например:
- Класс Cat переопределяет (override) метод sayAnything() класса Animal.
- @override - это опциональная аннотация (annotation), помещаемая перед переопределяемым методом (в подклассе). Если вы случайно переименуете этот метод в родительском классе, компилятор Dart выдаст вам сообщение об ошибке.
method_override_ex1.dart
class Animal {
void sayAnything() {
print('<Nothing>');
}
}
class Cat extends Animal {
@override
void sayAnything() { // Override method from parent class.
print('Meow');
}
}
void main() {
Animal animal = Cat();
animal.sayAnything();
}
Output:
Meow
Например: Используйте ключевое слово super для вызова метода родительского класса.
method_override_ex2.dart
class BoldFormatter {
String formatText(String text) {
return '<b>' + text + '</b>';
}
}
class BoldItalicFormatter extends BoldFormatter {
@override
String formatText(String text) { // Override method from parent class.
var boldText = super.formatText(text); // Call super method.
return '<i>' + boldText + '</i>';
}
}
void main() {
var formatter = BoldItalicFormatter();
var formattedText = formatter.formatText('Hello');
print(formattedText);
}
Output:
<i><b>Hello</b></i>
8. Final method?
В языке Java вы можете использовать ключевое слово final для метода, чтобы гарантировать, что подклассы не смогут переопределить (override) этот метод. Есть ли что-то подобное в Dart?
package:meta дает вам @nonVirtual, чтобы предотвратить переопределение подкласса методом родительского класса. Это помогает Analyzer (анализатору кода) сообщать об ошибке, если вы нарушаете это, но никаких других действий не предпринимается.
method_final_ex1.dart
import 'package:meta/meta.dart';
class Foo {
@nonVirtual
void bar() {
print("bar from Foo!");
}
}
class SubFoo extends Foo {
@override
void bar() {
print("bar from SubFoo");
}
}
В принципе, вы получите предупреждение (warning) от Analyzer, которое выглядит следующим образом:
The member 'bar' is declared non-virtual in 'Foo'
and can't be overridden in subclasses.dart(invalid_override_of_non_virtual_member)
- Thêm thư viện vào dự án Dart
Pуководства Dart
- Тип данных Boolean в Dart
- Функции в Dart
- Замыкания (Closure) в Dart
- Методы в Dart
- Свойства в Dart
- Оператор точка-точка (..) в Dart
- Программирование Dart с помощью онлайн-инструмента DartPad
- Установите Dart SDK в Windows
- Установите Visual Studio Code в Windows
- Установите Dart Code Extension для Visual Studio Code
- Установите Dart Plugin для Android Studio
- Запустите свой первый пример Dart в Visual Studio Code
- Запустите свой первый пример Dart в Android Studio
- Dart JSON với thư viện dart:convert
- Руководство Dart List
- Переменные в Dart
- Руководство Dart Map
- Циклы в Dart
Show More