"Магия" программирования

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

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

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

Волшебство ООП

Объектно-ориентированное программирование — мощнейший инструмент разработчика. Писать на современных языках гораздо удобнее, чем, допустим, на языке C. Например, для того чтобы вывести пользователю целое число, а не дробь, которая «крутилась» в уравнении, мне пришлось немного подумать. И написал я вот что:

Допустим, у нас есть некая переменная y, куда мы передали дробное значение:
float y = 2.0  
Проверить, целое это число или нет мы должны простыми средствами. Для этого создадим пустую переменную x, инициализируем её нулем и напишем такой код:
float a = y;
int x = 0;
x = (int)y;
y--=x;

if (x == 0) {
printf (“Наша переменная равна  %d”, x);
}
else {
printf (“Наша переменная равна %f”, a);
}

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

 

Объектно-ориентированное программирование избавлено от этих хлопот. Там чаще всего большинство технологий представлено в готовом виде. Так, например, в языке Java легко проверить корректность ввода методом parseInt из класса Integer пакета Java.lang. При вводе нецелого числа или вообще чего угодно, программа выдаст ошибку (исключение), которую программисту необходимо обработать должным образом — поместить туда фразу «вы допустили ошибку», перебросить пользователя обратно к окну ввода или даже дать ему ещё несколько пробных попыток. Но, собственно, мы сегодня не об этом, а о «волшебстве».

Магические классы

Самым настоящим чудом в ООП является тот факт, что программу можно писать не одним бесконечным листингом, как в C, а разбить её на файлы и блоки — классы и методы. Это просто здорово. Ведь в одном классе мы можем хранить запускающую функцию main, в других — методы нашей программы, в третьих — данные или интерфейс соединения с БД. Но как же нам реализовать наше волшебство? Не волнуйтесь — сейчас придумаем вместе.
Создадим, например, класс OneClass:
public class OneClass {
}
И поместим туда наши данные — несколько переменных.
public class OneClass {
int x = 9;
int y = 10;
int z = 11;
}

По умолчанию эти переменные имеют пакетный доступ — т. е – все классы (файлы) нашего пакета могут ими воспользоваться — скопировать, изменить, переопределить. Но как же это сделать? А очень просто — создать экземпляр нашего класса OneClass в другом классе или после метода main.
OneClass cl = new OneClass();

Теперь мы получили возможность пользоваться всеми методами и полями класса (так называются наши переменные, которые написаны сразу после имени класса и поэтому видны во всем OneClass). Скопируем их себе – создадим свои переменные и перебросим туда нужные значения:
public class TwoClass {
OneClass cl = new OneClass();
int x = cl.x;
int y = cl.y;
int z = cl.z;
}

Не стоит бояться одинаковых имен — в другом классе они не перепутаются с изначальными. И теперь у нас есть данные из класса OneClass. 

Но с ними нужно быть очень осторожными. Ведь мы не только можем взять их из первого класса, но и переписать их значения. И хорошо, если мы сделаем это обдуманно. А если просто? Непорядок. Что же делать? Волшебство нуждается в защите от ошибки.

Защитное волшебство

Речь, конечно, пойдёт не о заклятьях Гарри Поттера и не о «Властелине колец». Я хочу рассказать об удивительных методах — геттерах и сеттерах.

В прошлой главе мы выяснили, что если наши данные открыты для другого класса — это не очень хорошо. Ведь мы (или кто-то другой) можем нечаянно изменить их при использовании, просто создав собственный класс и записав там соответствующие инструкции. И объект, класс для которого мы так кропотливо создавали, может получить такие параметры, что превратится в самого настоящего орка из «Властелина колец».

Чтобы этого избежать, мы сделаем вот что: припишем к каждой переменной идентификатор, который запретит её использование везде, кроме собственного класса.
private x = 9;
private y = 10;
private z = 11;

Теперь никто со стороны не сможет наши данные изменить. Это называется инкапсуляцией. Ну а для нас пока это — волшебство. Попробуем в нём разобраться.
Чтобы создать новый объект, нам самим, другим программистам или иным частям программы, всё равно потребуется получить данные из нашего класса. И что же тогда делать? Ведь они закрыты? Именно для этих случаев и нужны геттеры. Но это волшебство мы должны создавать сами, прописав всю логику этих методов. Get — значит «читать». Чтобы прочитать наши данные в другом классе, нужно их скопировать и передать.

В классе OneClass напишем, например, для переменной x метод-геттер следующего содержания:
public int getX () {
return x;
}
В классе TwoClass вызываем этот метод:
class cl = new class();
cl. getX ();
Можем напечатать наше выражение и убедиться, что получена именно наша переменная.
System.out.println (cl. getX ());
Можно и записать что-то нужное в переменную класса. Для этого потребуется сеттер.
public void setY (newY) {
y =  newY;
}
Надпись, private int y = 10; останется на своем месте. Но получить из недр класса можно будет только то значение, которое записано в newY. Магия – да и только!
С помощью сеттеров мы можем, например, легко «приструнить» пользователя, принимая лишь числа больше нуля и меньше 10. Для этого в сеттер нужно записать несложную логику:
public void setY (newY) {
if (newY>0&& newY<10) {
y =  newY;
}

Магический конструктор

Конструктор — ещё одна магическая единица ООП. Его видно при создании нового объекта класса — например, OneClass cl = new OneClass(); Круглые скобки как раз и скрывают конструктор. Правда, в нашем случае он не имеет параметров, поскольку создается автоматически. Значит, что переменных у нашего объекта может быть любое количество всех типов. Но если мы напишем свой конструктор, то объект не только будет привязан к каким-то параметрам, которые нельзя изменить, но и может получить начальные значения.
Допустим, игровой юнит «дракон» по нашей задумке должен обладать скоростью, высотой полета, временем нахождения в воздухе и должен иметь несколько абстрактных единиц силы. Создадим соответствующий класс и конструктор:

public class Dragon {
Dragon(){
int speed = 120;
int flight_altitude = 1000;
int timeAir = 7;
int power = 10;
}
}

Итак, у нас есть дракон, который может мчаться со скоростью 120 километров в час на высоте 1000 метров целых семь минут! Вдобавок, он обладает 10 единицами силы, а это значит, что его противник должен будет очень долго с ним сражаться.
Вот так легко мы создали своего собственного дракона и инициализировали его по-настоящему волшебными свойствами. Добавить ему уже ничего нельзя, так как если конструктор с параметрами написан, то пустой сам по себе не создается. Но те свойства, что мы придали дракону, отнять невозможно. Теперь с нашим конструктором можно создавать целые полчища драконов, которые расчистят нам путь к сокровищам. Чудеса!

Волшебная перегрузка

Но и это — ещё не всё. И конструкторы, и методы поддерживают так называемую перегрузку — то ещё волшебство. Допустим, нам нужно создать из нашего класса Dragon не только дракона, а ещё и «берсеркера». У него не будет высоты и времени полёта — а скорость и сила останутся. Второй конструктор будет таким:
Dragon(int v, int c){
}

В классе, где будет расположен метод main для всех игровых юнитов,  инициализируем новые переменные другими значениями и добавим их в новый объект:
int speed = 60;
    int power = 7;
    Dragon berserker = new Dragon(speed, power);

Ап! У нас появился берсеркер!
Ещё одно маленькое чудо «на закуску». Если у нас в классе уже есть поля x, y, z, то в своем конструкторе или методе мы вполне можем создать такие же переменные с теми же именами и передать им значения полей. Причем наши переменные не перепутаются. Для этого только нужно вставить перед ними маленькое слово  с точкой, вот так:  this.
int x = 4;
int y = 6;
int z = 12;
Dragon(int v, int c, int z){
this.x = x;
this.y = y;
this.z = z;
}

В программировании полно вещей, которые можно назвать если и не магическими, то уж чудесными — абсолютно точно. И эти чудеса вполне под силу освоить любому желающему.

Эдуард Трошин

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Читайте также

 

Комментарии

Страницы

Аватар пользователя leo3

Get — значит «читать»

read значит "читать", а get - получить

Аватар пользователя leo3

Концепция ООП выросла из функционального программирования. В какой-то момент данные и методы их обработки объединили (инкапсулировали) т.е. поместили в единые капсулы - объекты. Объекты объединили в классы, установили возможность наследования, а также допустили полиморфизм. ООП - средство оживления параллельного графического интерфейса, а в более общем смысле - средство построения функциональных систем из взаимодействующих объектов.

Аватар пользователя leo3

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

Аватар пользователя leo3

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

Аватар пользователя mike

Концепция ООП выросла из функционального программирования.

Нет. ООП выросло из понятия "структура, переменных, порождаемая в ОЗУ". В тело которой добавили и процедуры (и/или функции). Т.е. исполняется не только загружаемый код, а и потомки его кусков.

Функциональный подход -- иное. Характерный признак -- использование имён функций среди аргументов функций.

...В ООП все функционирует как-бы параллельно...

Не обязательно. Так бывает только если создаётся несколько потоков.

Аватар пользователя Petro45

Инкапсуляцией называется не это.

Ну так откройте Википедию  и прочтите: икапсуляция - механизм языка, позволяющий ограничить доступ одних компонентов программы к другим

целесообразно придерживаться академического стиля написания кода

Это слишком сложно для начинающих и абсолютно им не поможет.

Это же обучающий материал по сути.

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

Аватар пользователя mike

Ну так откройте Википедию  и прочтите: икапсуляция - механизм языка, позволяющий ограничить доступ одних компонентов программы к другим

Ага. А если все члены класса объявлены, как public (кто запретит?), то инкапсуляция не состоялась?

Не читайте Вики поутру. 

Аватар пользователя mike

Это статья, которая должна заинтересовать людей, популяризирующая...

Лично я воспринял её, как отчёт о процессе вашего обучения.

Аватар пользователя mike

 Если бы я писал свои статьи в духе, который вы предлагаете - их бы, вообще, никто не читал.

Верно. Чёрт меня дёрнул написать про сохранённые процедуры. Ни минусов, ни плюсов! После чего желание писать Firebird vs MySQL отвалилось, как  усохший струп.

Аватар пользователя Petro45

Лично я воспринял её, как отчёт о процессе вашего обучения.

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

Страницы