Erinevus lehekülje "ITI0011RUS:Objects" redaktsioonide vahel

Allikas: Kursused
Mine navigeerimisribale Mine otsikasti
160. rida: 160. rida:
 
// (Other instance variables have default initial values of zero.)
 
// (Other instance variables have default initial values of zero.)
 
</source>
 
</source>
 +
 +
На рисунке ниже видно, как выглядят объекты в памяти, в случае данного примера:
 +
 +
[[Pilt:Java-juhend-Objects-in-heap.png]]
 +
 +
Если кака-либо переменная ссылается на объект - то это обозначено на картинке стрелкой. Видно, что <code>std</code>, <code>std1</code> и <code>std2</code> ссылаются на объект типа <code>Student</code>, причем <code>std1</code> и <code>std2</code> ссылаются на один и тот же объект. Если несколько переменных ссылаются на один объект, и через одну из переменных в объекте что-то меняют (например, имя), то при чтении этого поля через другие переменные, полуим новое (обновленное значение). Тоесть сама переменная - это лишь ссылка на область памяти (как бы адрес объекта в памяти). Если несколько переменных ссылаются на один и тот же объект в памяти, то при изменении чего-то в объекте все переменные "видят" это изменение.
 +
 +
Стоит обратить внимание на то, что <code>String</code> также является объектом - тоесть имя студента также является ссылкой на какую-то область памяти, где хранятся данные об имени.
 +
 +
Если переменной не примитивного типа (тип данных переменной является объектом) присваивается значение другой не примитивной переменной (в примере выше <code>std2 = std1</code>), то <code>std2</code> начнет указывать на тот же объект, что и <code>std1</code> - тоесть <code>std2</code> присваивается та же ссылка (адрес в памяти), что и у переменной <code>std1</code>. В результате такого присваивания обе переменные будут ссылаться на ту же самую область памяти. <code>std1.name</code> и <code>std2.name</code> будут ссылаться на одно и то же имя. Если, например, используя <code>std1</code> изменить имя, то при прочтении его используя <code>std1</code> имя сменится. <code>std1.name</code> и <code>std2.name</code> - две разные возможности сослаться на одну и ту же область памяти.

Redaktsioon: 16. märts 2015, kell 16:06

Вернуться на страницу предмета

Объект-ориентированное программироваие (OOП)

Объектно-ориентированное программирование (англ. object oriented programming, aka OOP) это разновидность программирования, при котором программа рассматривается как набор объектов. Java по большей части объектно-ориентировнный язык программирование (элементарные типыданных, такие как int, double и т.д. не являются объектами).

ООП это техника, которая позволяет сделать процесс программирования более удобным. Польза от этого подхода ощущается в особенности в больших проектах. ООП не делает ваши программы более быстрыми.

Основные цели ООП:

  • Инкапсуляция информации (encapsulation). Другие объекты могут пользоваться не всеми методами и переменными данного объекта, а только теми, которыми им разрешено пользоваться.
  • Модульность (modularity). Разделение кода на более или менее независимые модули - классы. Каждый класс выполняет одну конкретную задачу и только ему (классу) известными способами - другие модули не знают как какой-то конкретный модуль выполняет свои задачи - все, что им следует знать - это какой будет результат работы модуля при определенных входных данных, логика работы самого модуля - "черный ящик".
  • Полиморфизм (polymorphism). Один и тот же метод в разных объектах может вести себя по-разному.
  • Наследование (inheritance). Классы могут образовывать иерархию, в которой производные (под)классы наследуют определенные методы и переменные родительского класса, помимо этого, дополняют его своими собственными переменными и методами.
  • Повторное использование кода. Готовые модули, написанные для одной программы, могут использоваться повторно для других целей в других проектах.

Основная концепция ООП

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

Для описания состояния объекта используют следующие термины: атрибут (attribute), свойство (property), поле (объекта) ((instance) field), переменная (объекта) ((instance) variable).


Идеология ООП

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

ООП позволяет (в случае более крупных программ):

  • лучше структурировать код программы
  • поддерживать код в понятной для понимания форме
  • дополнения/изменения в код делать легче

и т.д.

Класс и объект

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

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

В ООП часто вместо термина объект используется термин экземпляр (instance) класса.

В языке Java свойства класса подразделяются на поля и методы класса:

  • статическое поле (public static int dogCount;) это переменная, принадлежащая классу (не объекту!). Если класс описывает всех собак, то и статическая переменная описывает также свойство всех собак. Если где-то (в каком-то месте кода) значение этого поля меняется - оно меняется во всей программе.
  • не статическое поле (String name;), также известное как переменная класса или переменная экземпляра, описывает свойства конкретного объекта (собаки), в данном случае, имя конкретной собаки. Имя каждой собаки может отличаться. Если изменить имя в одном объекте, в других объектах значение этого поля не поменяется.

Класс также описывает действия, или поведение объектов данного класса. Эти действия называются методами (фактически это просто функции, но в терминологии ООП они называются методами). Методы позволяют объектам выполнять те или иные действия. Например, у объектов класса "Собака" может быть метод лаять, который заставляет лаять конкретную собаку, в чьем объекте метод был вызван.

  • статический метод (public static int getDogLimit()), также называемый функцией или методом класса, это функция, которая принадлежит классу и не зависит от конкретного объекта. Например количество собак, которые могут находиться в конуре не зависит от конкретных собак. Это функция, единая в рамках всей программы.
  • не статический метод (public void bark()), также называемый функцией или методом объекта, привязан к конкретному объекту. Этот метод или функция вызывается отдельно для каждого объекта (можно вызывать этот метод и для всех объектов, вызвав этот метод у каждого объекта в отдельности).

Рассмотрим пример кода: <source lang="java">

/**

* Describes a student which
* has some test results.
*
*/

public class Student { /** * The name of the student. */ public String name; /** * Unique ID over all the students. */ public int ID; /** * The results of three tests. */ public double test1, test2, test3;

/** * Calculates the average test result. * @return Average test result */ public double getAverage() { return (test1 + test2 + test3) / 3; }

/** * Static variable which holds the next unique id. * The value of this variable is usually student count. * This is the same for all the students. */ private static int nextUniqueID = 0;

/** * Gets a unique ID for the student. * The ID number itself is increased. * @return Unique id for the student. */ public static int getUniqueID() { nextUniqueID++; return nextUniqueID; } }

</source>

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

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

Создание объектов

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

Таким образом, имя класса используется как тип данных. Например, мы можем создать переменную, у которой тип данных Student: <source lang="java"> Student std; </source>

В Javas объявление переменной (как показано в примере выше) еще не создает объект - мы только создаем переменную для хранения объектов данного типа данных. В общем:

  • В Java ни одна переменная не хранит объект в себе.
  • Переменная хранит лишь ссылку на объект (сам объект находится где-то в другой области памяти процесса).

Таким образом, в Java любая переменная для хранения объектов (все равно каких, созданных вами, или встроенных объеков Java), содержит в себе лишь ссылку на этот объект в памяти. Конкретное значение ссылки (reference) или указателя (pointer) программист не знает. При создании объекта, Java проиводит все необходимые действия (выделяет память для хранения объекта и сохраняет ссылку на эту область памяти в переменной).

Создание объекта осуществляется ключевым словом new: <source lang="java"> std = new Student(); </source>

Код выше создает новый объект класса Student в памяти, и записывает ссылку на этот объект в переменную std. Проинициализированная таким образом переменная std используется в качестве объекта. Чтобы обратиться к полям или методам данного объекта, можно использовать созданную переменную, например std.name .

Null ссылка

Бывают случаи, когда требуется показать, что переменная, подобная std, тип данных которой - класс, не ссылается ни на один существующий объект. В этом случае переменная std хранит так называемую null-ссылку или пустую ссылку (null reference). В Java null-ссылка обозначается как null. Можно присвоить переменной значение null-ссылки следующим образом: <source lang="java"> std = null; </source> и проверка, содержит ли переменная null-ссылку выглядит следующим образом: <source lang="java"> if (std == null) { </source>

Если значением переменной является null, то фактически у нас нет никакого объекта к которому можно было бы обратиться. Если например std = null;, то обращение к полю std.name приведет к исключению null pointer exception (NullPointerException).

Экземпляр класса

Конкретный объект называют экземпляром своего класса (instance). Ниже приведен пример того, как создавать различные экземпляры описанного ранее класса Student.

<source lang="java"> // Declare four variables of type Student Student std, std1, std2, std3; // Create a new object belonging to the class Student, // store a ref to that object in the var std. std = new Student(); std1 = new Student(); // Create a second Student object std2 = std1; // Copy the reference value in std1 into the variable std2. std3 = null; // Store a null reference in the variable std3. std.name = "John Smith"; // Set values of some // instance vars, getUniqueIdisa static method, // therefore is accessed from class Student // (not object instance like std) std.ID = Student.getUniqueID(); std1.name = "Mary Jones"; std1.ID = Student.getUniqueID(); // (Other instance variables have default initial values of zero.) </source>

На рисунке ниже видно, как выглядят объекты в памяти, в случае данного примера:

Java-juhend-Objects-in-heap.png

Если кака-либо переменная ссылается на объект - то это обозначено на картинке стрелкой. Видно, что std, std1 и std2 ссылаются на объект типа Student, причем std1 и std2 ссылаются на один и тот же объект. Если несколько переменных ссылаются на один объект, и через одну из переменных в объекте что-то меняют (например, имя), то при чтении этого поля через другие переменные, полуим новое (обновленное значение). Тоесть сама переменная - это лишь ссылка на область памяти (как бы адрес объекта в памяти). Если несколько переменных ссылаются на один и тот же объект в памяти, то при изменении чего-то в объекте все переменные "видят" это изменение.

Стоит обратить внимание на то, что String также является объектом - тоесть имя студента также является ссылкой на какую-то область памяти, где хранятся данные об имени.

Если переменной не примитивного типа (тип данных переменной является объектом) присваивается значение другой не примитивной переменной (в примере выше std2 = std1), то std2 начнет указывать на тот же объект, что и std1 - тоесть std2 присваивается та же ссылка (адрес в памяти), что и у переменной std1. В результате такого присваивания обе переменные будут ссылаться на ту же самую область памяти. std1.name и std2.name будут ссылаться на одно и то же имя. Если, например, используя std1 изменить имя, то при прочтении его используя std1 имя сменится. std1.name и std2.name - две разные возможности сослаться на одну и ту же область памяти.