Объектно-ориентированное программирование

Методы

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

Методы представляют функции, которые определены для структур или перечислений enum. Они позволяют добавить структурам и перечислениям некоторое поведение - некоторые выполняемые действия.

Формальное определение методов:

impl структура/перечисление {
	fn название_метода(&self){
		// выполняемые действия
	}
}

Определение методов заключается в конструкцию, которая определяется с помощью ключевого слова impl. После него идет название структуры или перечисления, для которого определяются методы.

Первый и обязательный параметр метода всегда представляет ссылку на объект структуры/перечисления, для которого запускается метод. Ссылка на объект структуры/перечисления передается с помощью &self.

Например, пусть у нас есть некоторая структура Person:

struct Person
{
    name: String,
    age: u8 
}

Добавим к этой структуре метод, который будет выводить ее данные на консоль. Для этого пропишем следующий код:

impl Person{
	
	fn display(&self){
		println!("Name: {}  Age: {}", &self.name, &self.age);
	}
}

После оператора impl указывается название структуры, для которой создается метод - структуры Person.

Метод называется display(). Он имеет только один параметр - ссылку на объект структуры, который будет вызывать данный метод - &self.

В самом методе с помощью ссылки на объект структуры мы можем обратиться к ее данным:

println!("Name: {}  Age: {}", &self.name, &self.age);

Вызов метода происходит в следующем формате:

название_объекта.название_метода();

После названия объекта структуры через точку указывается имя метода, после которого в скобках перечисляются значения для параметров метода. (Для параметра &self значение передается автоматически)

Теперь используем выше определенные структуру и метод:

fn main(){
	
	let tom = Person{
		name: "Tom".to_string(),
		age: 36
	};
	tom.display();
	
	let bob = Person { name: "Bob".to_string(), age: 41};
	bob.display();
}
struct Person
{
    name: String,
    age: u8 
}
impl Person{
	fn display(&self){
		println!("Name: {}  Age: {}", &self.name, &self.age);
	}
}

Консольный вывод программы:

Name: Tom	Age: 36
Name: Bob	Age: 41

В данном случае создается два объекта структуры Person: tom и bob. При вызове

tom.display();

В качестве ссылки на текущий объект &self передается ссылка на объект tom, поскольку этот объект вызывает данный метод. При этом при вызове метода для параметра &self не надо передавать никаких значений. Поэтому при вызове метода мы не передаем ему никаких параметров.

Аналогично при вызове

bob.display();

В метод будет передаваться ссылка на объект bob, поэтому этот вызов метода выведет на консоль данные для объекта bob.

Стоит отметить, что в принципе мы здесь используем еще один метод - метод to_string(), который преобразует значение к типу String:

name: "Tom".to_string(),

Передача параметров в метод

Как и любая функция метод может принимать и другие параметры Например, добавим метод, с помощью которого один объект Person будет приветствовать другой объект Person:

fn main(){
	
	let tom = Person { name: "Tom".to_string(), age: 36};
	let bob = Person { name: "Bob".to_string(), age: 41};
	tom.say_hello(&bob, 12);
	bob.say_hello(&tom, 19);
}

struct Person { name: String, age: u8 }
impl Person{
	
	fn say_hello(&self, other: &Person, hour: u8){
		if hour < 16{
			println!("Добрый день, {}!", other.name);
		}
		else {
			println!("Добрый вечер, {}!", other.name);
		}
	}
	fn display(&self){
		println!("Name: {}  Age: {}", self.name, self.age);
	}
}

Итак, здесь добавлен метод say_hello(), который принимает три параметра. Первый параметр традиционно - ссылка на текущий объект. Второй параметр - other представляет ссылку на структуру Person - человека, которого надо приветствовать. И третий параметр - hour - текущий час. В самом методе в зависимости от текущего часа выводим на консоль то или иное приветствие.

Поскольку метод принимает три параметра, то при вызове метода в него надо передать два значения - для второго и третьего параметра (как уже говорилось выше, для первого параметра передавать никаких значений не надо):

tom.say_hello(&bob, 12);

Консольный вывод программы:

Добрый день, Bob!
Добрый вечер, Tom!

Возвращение результата из метода

Также, как и обычные функции, метод может возвращать некоторое значение. Например, определим метод, который будет сравнивать два объекта Person по возрасту - кто старше и в зависимости от проверки возвращать некоторый результат:

fn main(){
	
	let tom = Person { name: "Tom".to_string(), age: 36};
	let bob = Person { name: "Bob".to_string(), age: 41};
	
	let is_older = tom.is_older(&bob);
	
	if is_older{
		println!("{} старше чем {}", tom.name, bob.name);
	}
	else{
		println!("{} младше чем {} или одного возраста с ним", tom.name, bob.name);
	}
}

struct Person { name: String, age: u8 }
impl Person{
	fn is_older(&self, other: &Person) -> bool{
		
		self.age > other.age
	}
}

Метод сравнения на возраст называется is_older(). В качестве параметра он принимает объект Person, с которым проводится сравнение. В качестве результата метод возвращает значение типа bool: true, если возраст текущего объекта Person больше возраста объекта other, либо false, если возраст меньше или равен.

При вызове в метод передается значение типа Person:

let is_older = tom.is_older(&bob);

Полученный из метода результат сохраняется в переменную is_older. Поскольку этот результат представляет тип bool, то мы можем использовать в конструкции if..else и в зависимости от его значения вывести на консоль то или иное значение. В данном случае консольный вывод будет следующим:

Tom младше чем Bob или одного возраста с ним

Изменение текущего объекта в методе

Если необходимо изменять текущий объект в методе, то первый параметр метода определяется как изменяемая ссылка - &mut self. Например:

fn main(){
	
	let mut tom = Person { name: "Tom".to_string(), age: 36};

	println!("До изменения: {}", tom.age);		// 36
	tom.change_age(22);
	println!("После изменения: {}", tom.age);	// 22
}

struct Person { name: String, age: u8 }
impl Person{

	fn change_age(&mut self, age: u8){
		
		self.age = age;
	}
}

В данном случае определен метод change_age(), который изменяет возраст текущего объекта Person с помощью второго параметра. Соответственно первый параметр определен как &mut self. Кроме того, переменная, которая представляет текщий объект определена с mut:

let mut tom = Person { name: "Tom".to_string(), age: 36};
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850