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

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

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

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

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

Объектно-ориентированное программирование — мощнейший инструмент разработчика. Писать на современных языках гораздо удобнее, чем, допустим, на языке 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!

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

 

Комментарии

Страницы

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

Отчет будет позже. ... Это - именно популярная статья...

Ну не весь отчёт, а отчёт об очередном этапе. Я так воспринимаю. Другие, возможно, по-другому.

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

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

Так переобъявите их как private. Это же хороший тон для тех, кто знаком с инкапсуляцией!:-)

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

Так переобъявите их как private.

В некоторых случаях это не представляется возможным.

"Объект это то, что заключено в фигуристые скобочки" (C)

Пример из Javasсript:

var myObject = {};

Просто красота и сама лаконичность. Имхо, конечно, имхо

Smile

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

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

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

Для журналиста вообще-то неплохо, суть он уловил. Но не всю.

Аватар пользователя zabanen
Впрочем, чтобы глубоко понимать суть, имхо надо хотя бы раз попытаться написать компилятор. Ну или изрядно пописать на асме. Этому учат не на курсах, а в универе на соответствующих специальностях.
Аватар пользователя zabanen

В некоторых случаях это не представляется возможным.

Да и не нужным. Объект может содержать только методы, доступные другому объекту, не обязательно дружественному. Пример: объект, предоставляющий пользователю доступ к БД, содержащий набор SQL-запросов. Работающее приложение создаёт такой новый объект каждый раз, когда к БД подключается новый пользователь, и уничтожает, если  пользователь отключается.

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

Будут ли члены капсулы приватными, защищёнными, публичными или опубликованными (бывают и такие) -- это другое и решается по ходу разработки.

Но в пособиях для неофитов с целью упрощения всё сваливают в кучу.

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

Но в пособиях для неофитов с целью упрощения всё сваливают в кучу

Да, это очень чувствуется - в огороде бузина, а в Киеве - дядька + божий дар с яичницей...:)

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

Да, это очень чувствуется - в огороде бузина, а в Киеве - дядька + божий дар с яичницей...:)

Критика - это великолепно для статьи, поскольку дискуссионные комментарии значительно повышают её рейтинг и читабельность. Я искренне доволен, что вас обоих так удачно задел (особенно вас).:-) В ваших словах чувствуется искренняя ревность и даже немного зависти.

Поэтому, замечу, что вам самому надо было бы давно написать что-то подобное, в присущем вам идеальном ключе, так сказать, продемонстрировать нам "класс". Сочинили бы программку в стиле ООП, продемонстрировали бы её работу и все нюансы. И я бы взял с вас пример и другим начинающим была бы методическая помощь.

А так приходится делать всё самому: писать программы, штудировать буржуазных недоучек, вроде Кнута, Кернигана и Гослинга и довольствоваться скупыми и малоинформативными комментариями отечественных мэтров программирования. :-) 

Короче, Склихосовский....:-)

Страницы