Kodomo

Пользователь

Учебная страница курса биоинформатики,
год поступления 2010

ООП в Java: классы, объекты

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

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

Вам должно быть все это уже знакомо из Python, а в особенности тем, кто делала задачки про моделирование популяции или ей подобные.

Если вы задумаетесь, как вы представляете мир у себя в голове, то скорее всего ваш взгляд на мир окажется как раз объектно-ориентированным. Вот, например, про секретаршу мы хотим знать ее имя, фамилию и длину ногтей. А про боса — имя, фамилию и насколько часто он спит и ничего не делает. Бос и секретарша, очевидно, - объекты разных типов (или классов). Они обладают разным набором свойств и выполняют различный набор действий. При этом объекты одного класса имеют один и тот же набор свойств, однако отличаются разными значениями этих свойств. Например, секретарша Маша Иванова с ногтями в 30 мм и Настя Петрова с ногтями в 3 мм — это разные объекты класса секретарш.

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

   1 class Secretary
   2 {
   3         String name;
   4         String surname;
   5         int nails_length;
   6 }

В Java традиционно принято, чтобы каждый класс находился в отдельном файле и назывался с большой буквы. А теперь давайте создадим нашу виртуальную секретаршу - объект класса Secretary.

   1 Secretary secretary = new Secretary();

Давайте разберем, что здесь написано. Когда мы пишем new, создается объект заданного типа. А раз есть объект, он занимает какое-то место в памяти — так вот в этот момент где-то в памяти компьютера выделяется область, в которую кладется созданный объект. А через переменную secretary мы можем обращаться к нашему объекту. Другими словами secretary — это ссылка на реальный объект секретарши. На самом деле, она просто хранит адрес ячейки памяти, где лежит объект. Раз это просто ссылка, то нет никаких препятствий, чтобы существовало несколько ссылок на один и тот же объект.

То есть если мы напишем:

   1 Secretary secretary2 = secretary;

Мы таким образом не создадим никакого нового объекта (нет new!) и не скопируем имеющийся. Просто теперь на наш объект "смотрят" две переменные: secretary и secretary2. Теперь если мы напишем

   1 secretary2 =null;

это не будет значить, что мы стерли объект секретарши из памяти. Просто мы убрали ссылку на него.

Обратите внимания, что ссылка на объект может быть только того же типа, что и объект.

А теперь обратимся к нашей новоявленной секретарше. Пока ее никак не зовут и ногти у нее обрезаны под корешок. Давайте исправим эту оплошность. Делается это так:

   1 secretary.name = "Маша";
   2 secretary.surname = "Иванова";
   3 secretary.nails_length = 30;

Таким образом, к свойствам объектам можно обратиться, написав имя объекта, затем точку и имя поля.

Методы

Но в Java объекты могут не просто существовать. Как и в жизни, они еще могут что-то делать и взаимодействовать друг с другом. Вот например, секретарши могут говорить, красит ногти, а еще распечатывать документы. Это реализуется с помощью методов класса. Функциональность класса – это по сути такое же свойство его объектов, как и поля. Все объекты класса должны обладать одинаковой функциональностью – т.е. все секретарши должны уметь говорить, красить ногти и печатать документы. Иначе они не секретарши :).

Про то, как описывать методы вам уже рассказывали на прошлом занятии. Так что давайте "оживим" нашу секретаршу, дописав в класс несколько методов.

   1 class Secretary
   2 {
   3         String name;
   4         String surname;
   5         // String – это тоже класс в Java и позже мы расскажем о нем подробнее, а
   6         // сейчас относитесь к переменным типа String просто как к строчкам.
   7         
   8         int nails_length;
   9         
  10         void speak(String phrase)
  11         {
  12                 System.out.println(getName()+":\t-"+phrase);
  13         }
  14 
  15         void paintNails()
  16         {
  17                 speak("I want to paint my nails. I'm busy now!");
  18         }
  19 
  20         // Секретарша печатает документы, только если она в не красит ногти (что случается с 
  21         // вероятностью, пропорциональной длине ее ногтей).
  22         // Обратите внимание, что в теле этого метода вызывается другой метод класса - speak().
  23         // Метод возвращает переменную булевского типа: true, если секретарше удалось
  24         // напечатать документы, false — если она решила вместо этого покрасить ногти.
  25         boolean printDocuments()
  26         {
  27                 double nails_probability = (double) nails_length / 35;
  28                 double prob = Math.random();
  29                 if (prob < nails_probability)
  30                 {
  31                         paintNails();
  32                         return false;
  33                 }
  34                 speak("Boss, all documents are printed!");              
  35                 return true;
  36         }
  37 
  38         // Этот метод просто возвращает имя секретарши. 
  39         // Теперь узнать имя секретарши мы можем двумя способами:
  40         // secretary.name и secretary.getName() 
  41         // Хорошим томом считается обращаться к переменным не непосредственно, а через методы. 
  42         // Это позволяет избежать многих ошибок.
  43         String getName()
  44         {
  45                 return name;
  46         }
  47 }

В Java традиционно принято называть методы с маленькой буквы.

Конструкторы

В классе мы можем сразу прописать инструкцию создания объекта. Например, чтобы секретарша сразу создавалась с именем, фамилией и ногтями определенной длины. Делается с помощью конструкторов (тоже знакомое понятие из Python).

Синтаксически они подобны методам. Они создают объект данного класса с данными параметрами и возвращают его:

   1 Secretary(String name,String surname,int nails_length)
   2 {
   3         this.name = name;
   4         this.surname = surname;
   5         this.nails_length = nails_length;
   6 }

Называются они всегда так же, как класс. Ключевое слово this указывает, что я хочу обращаться к свойствам объекта данного класса, а не к локальным переменным (аналогично self в Python). Локальная переменная может иметь то же имя, что и свойство объекта, и слово this помогает их различать.

Теперь мы можем одновременно создавать объект секретарши и инициализировать переменные класса:

   1 Secretary secr_mary = new Secretary("Marie", "Johnson", 30);

И теперь если вы спросите, как зовут эту секретаршу:

   1 System.out.println(secr_mary.getName());

То окажется, что ее зовут "Marie".