Найти в Дзене
В мире животных

Прекратите оскорблять (виртуальных) животных при обучении программированию

Многие из вас, читая учебник по программированию, сталкивались с таким примером:
/*
** Inheritance is useful when different classes share functionality. */
using System; class Animal
Оглавление

Многие из вас, читая учебник по программированию, сталкивались с таким примером:

/*
** Inheritance is useful when different classes share functionality. */
using System; class Animal
{
protected string speakSound = "";

public void Speak() {
Console.WriteLine(speakSound);
}
}

class Cat : Animal
{
public Cat() {
this.speakSound = "Meow";
}
}

class Dog : Animal
{
public Dog() {
this.speakSound = "Woof";
}
}

class ZooClass
{
static void Main(string[] args) {
Cat cat = new Cat();
Dog dog = new Dog();

cat.Speak(); // Prints Meow
dog.Speak(); // Prints Woof
}
}

А многие, прочитав этот пример, подумают:

«Да, я знаю, как использовать это в реальном приложении»

-2

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

Это все равно, что объяснять молоток как «полезный инструмент, у которого есть деревянная часть и металлическая часть, и при ударе чего-то металлической частью он начинает биться».

Шаблоны и методы программирования - это инструменты, которые используются, чтобы упростить реализацию сложного поведения или логики, сохраняя при этом поддерживаемость кода и легкость его построения.

Большинство примеров из реальной жизни могут быть слишком сложными для начинающих, но я думаю, что существует золотая середина между примерами из реальной жизни из 1000 строк и «Корова идет мычание».

Обучение на реальном примере из реального проекта

Начни с реальной проблемы. Если возможно, в реальном проекте (без каких-либо деталей, не имеющих отношения к рассматриваемой проблеме)

Движок стратегии в реальном времени с открытым исходным кодом для ранних игр Westwood, таких как Command & Conquer: Red Alert, написанный на C »

-3

В этой игре вы можете построить отряд под названием «Шпион», который может проникать в здания врага и, в зависимости от того, в какое здание проникают, может вызывать различные эффекты.

Некоторые примеры включают (из CNC Wiki):

Аэродром Отображает производимый в настоящее время.
Юнит при выборе здания.Отображает количество боеприпасов на приземлившихся самолетах.
Силовая установка Отображает вертикальный индикатор состояния силы врага в виде пяти квадратов.
Завод по переработке руды Отображает показатель мощности и количество руды, находящейся на данный момент.

Теперь вот проблема: как мне реализовать различные эффекты проникновения?

// Not like this
if (building.name == "Airfield") { airfieldInfiltration(); }
if (building.name == "Power Plant") { powerPlantInfiltration(); }
if (building.name == "Ore Refinery" { oreRefineryInfiltration(); }

В большинство зданий невозможно проникнуть, поэтому создание базового класса не кажется правильным, но все здания имеют совершенно разные действия, поэтому объединение всего в один класс тоже не кажется правильным.

После того, как читатель поймет проблему, вы представите решение:

Интерфейсы

OpenRA использует интерфейс под названием INotifyInfiltrated (объявленный здесь), который используется для реализации различных функций, когда шпион входит во вражеское здание.

Интерфейс реализован для любых зданий, в которые можно проникнуть, и поведение эффекта обнаруживается внутри каждого из различных классов зданий, а не в базовом классе или некотором огромном объекте операторов if-else.

Пример кражи денег с использованием интерфейса можно найти здесь. Обратите внимание, что поведение заключено в свои собственные классы, потому что здания не запрограммированы жестко, поэтому он не строго следует приведенному примеру, но нет причин, по которым это невозможно.

public interface INotifyInfiltrated {
void Infiltrated(Player playerInfiltrating);
}

class Airfield : INotifyInfiltrated
{
public void Infiltrated(Player playerInfiltrating) {
// Displays currently produced unit when
// the building is selected
Unit producingUnit = this.GetCurrentlyProducingUnit()
producingUnit.revealToPlayer(playerInfiltrating);

// Displays amount of ammunition on
// currently landed aircraft
Unit landedUnit = this.GetCurrentlyLandedUnit();
landedUnit.revealStatsToPlayer(playerInfiltrating);
}
}

class PowerPlant : INotifyInfiltrated
{
public void Infiltrated(Player playerInfiltrating) {
// Displays a five-box vertical indicator
// of enemy power status
this.revealPowerStatusToPlayer(playerInfiltrating);
}
}

class OreRefinery : INotifyInfiltrated
{
public void Infiltrated(Player playerInfiltrating) {
// Displays capacity indicator
//and amount of presently held ore
this.revealOreStatusToPlayer(playerInfiltrating);
}
}

Теперь читатель увидел реальный пример того, как интерфейс используется для решения реальной проблемы программирования. Они могут применять это всякий раз, когда сталкиваются с подобной проблемой, когда необходимое поведение «одинаково для некоторых, но не для всех».

Так что, прочитав это, возможно, в следующий раз, когда кто-то спросит об интерфейсах, вам не придется заставлять бедных виртуальных кошек и собак лаять и мяукать, чтобы выразить свою точку зрения.

Спасибо за просмотр! С тобой было интересно, оставь комментарий и подпишись. Еще больше интересного будет.