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

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

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

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

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

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

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

 

Комментарии

Страницы

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

в каком смысле?

В том смысле, что Логик идиотничает, как обычно. :-) "Объект это то, что заключено в фигуристые скобочки". ЖабаСкрипт == JavaScript.

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

Ну в этих словах Логика доля мысли, имхо, есть:) Это, действительно, то, что заключено в фигуристые скобочки:) в некотором смысле:) Это примерно как визатор показывал пацаков и чатлан:)

var obj = {}; - вполне допустимая в "ЖабаСкрипте" конструкция... и философская, имхо...:)

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

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

 

Цитата: 

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);
}

Автор, ну нельзя же так. Это же галиматья. Среди читателей, возможно, найдутся и те, кто знает C/C++.

И ещё. Вот вы пишете

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

 Причём здесь ООП?! Подобные задачи решаются языковыми средствами без всякого ООП. См. в сторону  операторов typeid и dynamic_cast.

Рискую опять получить бан ни за что, но я не советую писать статьи при недостаточном владении предметом. Даже "для детишек".

 

 

 

 

 

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

Майк совершенно прав...

brat-0> Ничего подобного. В ЖабаСкрипте - вообще, скобочек нет:  numX1 = objResult.x1;

Там, ДО ТОГО было:

var objResult = {}; // ВОТ ОНИ ФИГУРИСТЫЕ СКОБОЧКИ!!! Smile

objResult.x1 = "hello";

Внимательнее надо, brat-0, внимательнее.

brat-0> В Objective-C скобки квадратные:-) MyClass *myObject = [[MyClass alloc] init];

"Objective-C устарел." (С)


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

Рискую опять получить бан ни за что, но я не советую писать статьи при недостаточном владении предметом. Даже "для детишек".

Эти строчки я скопировал со своего компилятора GCC, могу прислать вам исполняемый файл. ООП тут ни при чем, шла речь о том, что чистый С (не С++) поддерживает не так много функций.

Причем я проверял этот код на Java и на C. На чистом С никаких функций проверок нет - спросите у кого угодно. Так и хочется вас послать иногда. Сами ни хрена не знаете, а лезете. Не надо варежку попусту открывать, а то я и правда обидеться могу. 

"Objective-C устарел." (С)

Тогда устарели и Айфоны, Логик. И App Store - вчерашний день? Это так?

 

brat-0 > Тогда устарели и Айфоны, Логик. Это так?

Нет, конечно. НЕ так.

"Objective-C устарел." (С) и на его место придумали более современный язык SWIFT.

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

"Objective-C устарел." (С) и на его место придумали более современный язык SWIFT.

Пока ещё на нем все работают, Логик. Кто пожелает проверить мой код - вышлю полный рабочий файл C с проверкой на целое число через присвоение. На другом языке могу это написать. 

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

Я проверял этот код... Обидеться могу..

OK. Попросите кого-нибудь проверить еще раз. Обижаться, конечно, имеете право, но обзываться -- нет. Тем более "алкашом". 

Страницы