Дисциплины - Объектно-ориентированное программирование

ООП в JavaScript - Разработка игры "Танчики" с использованием принципом объектно-ориентированного программирования

Давайте напишем класс Tank, у которого будет 2 метода: moveTo (переместисьВ) и fireTo (стельниВ). Реализацию методов пока не пишем, это просто заготовки:

class Tank {
	moveTo(x, y) {
	
	}

	fireTo(x, y) {
	
	}
}

С помощью этого класса мы сможем создать хоть сотню танчиков с однотипным поведением: каждый из них сможет перемещаться в нужную точку и стрелять.

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

var tank = new Tank; //в переменной tank теперь объект класса Tank

Давайте теперь создадим новый танк и вызовем метод moveTo, чтобы танк переместился в нужную точку:

var tank = new Tank;
tank.moveTo(10, 20); //командуем перемещение

Давайте сделаем два танка и каждый из них переместим в заданную точку:

var tank1 = new Tank;
tank1.moveTo(10, 10);

var tank2 = new Tank;
tank2.moveTo(20, 20);

Пусть второй танк стрельнет в точку нахождения первого:

var tank1 = new Tank; //создаем первый танк
tank1.moveTo(10, 10); //командуем перемещение в точку 10, 10

var tank2 = new Tank; //создаем второй танк
tank2.fireTo(10, 10); //командуем выстрел в местонахождение первого

Пусть у каждого созданного танка будет еще и свойство ammunition. В нем мы будем хранить количество снарядов танка.

Давайте создадим новый танк и в момент создания положим в него 10 снарядов:

var tank = new Tank;
tank.ammunition = 10;

При создании танка мы следующей строчкой на лету создали ему свойство ammunition. Теперь это свойство доступно внутри любого метода класса вот так: this.ammunition:

class Tank {
	fireTo() {
		//тут доступны снаряды через this.ammunition
	}
}

В данном случае this указывает на объект нашего класса. То есть: если мы вызываем метод fireTo для первого танчика, то this будет указывать на него, а если для второго танчика - то на него.

Давайте при каждом выстреле будем уменьшать количество снарядов на один:

class Tank {
	fireTo() {
		this.ammunition = this.ammunition - 1; //уменьшаем количество снарядов
	}
}

Иногда нам может потребоваться вызывать метод одного класса внутри другого. К примеру, мы хотим сделать метод moveAndFire, который будет перемещать танк и одновременно делать выстрел. Но у нас уже есть методы moveTo и fireTo - используем их внутри нового метода, чтобы избежать дублирования кода.

Для этого также, как и при работе со свойствами, к методам следует обратиться через this, вот так: this.moveTo() и this.fireTo:

class Tank {
	moveTo(x, y) {
	
	}

	fireTo(x, y) {
	
	}

	moveAndFire(moveX, moveY, fireX, fireY) {
		this.moveTo(moveX, moveY);
		this.fireTo(fireX, fireY);
	}
}

Конструктор

Мы задавали количество снарядов в танке при создании:

var tank = new Tank;
tank.ammunition = 10; //количество снарядов

На самом деле это не очень удобно, ведь эту строчку легко забыть написать - и танк будет безоружен. Лучше было бы, чтобы танк уже в момент создания был обеспечен нужным количеством снарядов.

Исправить это проблему нам поможет метод-конструктор. Этот метод имеет стандартное название constructor и вызывается автоматически в момент создания объекта (когда мы пишем new).

Давайте создадим танк и в момент создания выведем что-нибудь алертом на экран:

class Tank {
	constructor() {
		alert('создание');
	}
}

var tank = new Tank; //выведет 'создание'

Так же, как и в остальные методы, в конструктор можно передавать параметры. Давайте передадим в него параметр message и выведем его содержимое алертом на экран:

class Tank {
	constructor(message) {
		alert(message+'!');
	}
}

var tank = new Tank('создание'); //выведет 'создание!'

Давайте теперь исправим описанное выше неудобство - пусть количество снарядов задается прямо в конструкторе:

class Tank {
	constructor() {
		this.ammunition = 10; //положим 10 снарядов в момент создания
	}

	fireTo(x, y) {
		this.ammunition = 	this.ammunition - 1;
	}
}

Теперь каждый созданный танк будет иметь 10 снарядов уже в момент создания. Убедимся в этом:

var tank = new Tank;
alert(tank.ammunition); //выведет 10

А еще лучше давайте сделаем параметр, в который будем передавать количество снарядов в момент создания танка, вот так:

var tank = new Tank(10); //создаем танк с 10-ю снарядами
alert(tank.ammunition); //выведет '10'

Для этого в конструкторе напишем параметр ammunition, вот так: constructor(ammunition). Этот ammunition будет содержать в себе десятку, которую мы передаем в момент создания.

При этом переменная ammunition будет локальной переменной внутри конструктора. В данном случае нам это не нужно - мы хотели бы, чтобы количество снарядов было доступно во всех других методах (вот так: this.ammunition), а также снаружи объекта (вот так: tank.ammunition).

Для этого давайте запишем содержимое переменной ammunition в свойство ammunition, вот так: this.ammunition = ammunition.

Реализуем указанное:

class Tank {
	constructor(ammunition) {
		this.ammunition = ammunition; //запишем 10-тку в свойство объекта
	}

	fireTo(x, y) {
		this.ammunition = this.ammunition - 1;
	}
}

С помощью этого кода мы можем создать танк, положить в него нужно количество снарядов, а также пострелять с помощью метода fireTo.

Вот этот код:

class Tank {
	constructor(ammunition) {
		this.ammunition = ammunition;
	}

	fireTo(x, y) {
		this.ammunition = this.ammunition - 1;
	}
}

var tank = new Tank(10); //создаем танк
tank.fireTo(10, 20); //командуем выстрел

Если мы немного постреляем - с каждым выстрелом количество снарядов будет уменьшаться:

var tank = new Tank(10);
alert(tank.ammunition); //выведет '10'

tank.fireTo(10, 20); //скомандуем выстрел
alert(tank.ammunition); //выведет '9'

tank.fireTo(10, 20); //скомандуем выстрел
alert(tank.ammunition); //выведет '8'

Есть проблема: если выстрелить более 10 раз, то танк не перестанет стрелять - он будет выводить 0, -1, -2 и так далее. Все потому, что мы не запрещаем выстрел, если количество снарядов достигло нуля.

Давайте реализуем вспомогательный метод canFire(), который будет проверять, не закончились ли снаряды:

class Tank {
	constructor(ammunition) {
		this.ammunition = ammunition;
	}

	fireTo() {
		//Перед выстрелом проверяем снаряды:
		if (this.canFire()) {
			this.ammunition = this.ammunition - 1;
		}
	}

	//Вспомогательный метод для проверки снарядов:
	canFire(ammunition) {
		if (ammunition > 0) {
			return true;
		} else {
			return false;
		}
	}
}

Всем методам и свойствам, которые не должны быть видны снаружи, в начале названия добавляется подчеркивание (знак _). Давайте переименуем метод canFire в _canFire:

class Tank {
	constructor() {
		this.ammunition = 10;

	}

	fireTo() {
		if (this._canFire()) {
			this.ammunition = 	this.ammunition - 1;
		}
	}

	_canFire(ammunition) {
		if (ammunition > 0) {
			return true;
		} else {
			return false;
		}
	}
}

Количество комментариев: 0

Для того, чтобы оставить коментарий необходимо зарегистрироваться
814301 БГУИР
814302 БГУИР
814303 БГУИР
894351 БГУИР
90421 БГУИР


Изображения Видео

1. Абстрактная фабрика https://www.youtube.com/watch?v=1mVONOCxfLg
2. Фабричный метод https://www.youtube.com/watch?v=5UqUDR6_2cY
3. Шаблон декоратор https://www.youtube.com/watch?v=Lwb9bm8yKD0
4. Dessign patterns on PHP https://github.com/domnikl/DesignPatternsPHP
5. Приёмы объектно-ориентированного проектирования. Паттерны проектирования Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес; [пер. с англ.: А. Слинкин науч. ред.: Н. Шалаев]. — Санкт-Петербург [и др.] : Питер, 2014. — 366 с. : ил. ; 24 см.
6. Приемы объектно-ориентированного проектирования. Паттерны проектирования Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес; [пер. с англ.: А. Слинкин науч. ред.: Н. Шалаев]. — Санкт-Петербург [и др.] : Питер, 2014. — 366 с. : ил. ; 24 см.
7. Ajax http://erud.by/ajax
8. Ajax http://erud.by/ajax
9. Ajax http://erud.by/ajax
10. Документация Laravel http://laravel.com
Задание к курсовой работе
Задание к курсовой работе
Вопросы к экзамену