Журнал LinuxFormat - перейти на главную

LXF84:Java

Материал из Linuxformat
Перейти к: навигация, поиск

Содержание

Сказка Java

ЧАСТЬ 1: От кофеварок до промышленных серверов и биллинговых систем - Java можно встретить буквально везде. Начните изучение этой технологии вместе с Антоном Черноусовым.

Начиная ряд статей о программировании на объектно-ориентированном языке Java, хотел бы выразить свое мнение относительно корпоративного рынка разработки программного обеспечения, на котором в данный момент борются за лидерство два гиганта, две платформы: J2EE и .NET.

В основе платформы J2EE лежит язык программирования Java – приложения, созданные с его помощью, являются кроссплатформенными, сам язык, средства разработки и технология активно поддерживаются многими корпорациями: Sun, Google, IBM, Oracle, BEA. Платформа пользуется большой популярностью и среди компаний, ориентированных на OpenSource, таких как Apache Foundation. В противовес J2EE, корпорация Microsoft предлагает свою технологию .NET, которая является колоссом, построенным на мощи программного обеспечения Microsoft.

Сегодня еще нельзя сказать, какая технология станет доминирующей, и, возможно, от вас зависит скорость распространения современной кроссплатформенной технологии создания приложений J2EE и языка программирования Java.

Предложенные вашему вниманию уроки позволят овладеть основными понятиями Java и создавать различные приложения с его помощью. Рассмотрев основы языка, мы сможем изучить типовые решения (паттерны) в программировании и приступить к изучению J2EE. В первом уроке мы создадим свое первое приложение и разберемся с основными понятиями: инкапсуляция, наследование и полиморфизм. Для выполнения этого урока нам понадобится пакет Java SDK 1.5, текстовый редактор и немного терпения.

Героический объект

Приступая к этой серии материалов, я вспомнил, что, как правило, изучение языков программирования начинается с написания приложения "Hello World!", но такой прием настолько изъезжен, что я намереваюсь предложить пример поинтереснее: мы напишем приложение, рассказывающее сказку. Основа приложения – два класса. Каждый класс содержит члены двух видов: атрибуты и методы. Атрибуты – это данные, принадлежащие самому классу. Совокупное значение атрибутов определяет состояние объекта или класса. Метод – это последовательность операторов, изменяющих значения атрибутов и, как следствие, состояние класса или объекта.

В каждой интересной сказке должен быть свой герой. Предлагаю взглянуть на класс, который реализует нашего героя. Итак, по порядку. Следующий код необходимо сохранить в файл FirstHero.java.

public class FirstHero {
  private String quest;
  public FirstHero(String Quest) {
    this.quest = Quest;
  }
  public void setQuest(String Quest){
    this.quest = Quest;
  };
  public String getQuest(){
    return quest;
  };
}

Расположение одного класса в одном файле считается хорошим тоном среди программистов на Java – так что приучайтесь к нему сразу. Имя файла должно совпадать с названием класса, расширение у файла – .java.

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

Вы можете заметить, что первый метод (третья строка представленного ранее листинга) имеет то же название, что и класс – FirstHero. Такой метод называется конструктором. Конструктор – это метод, который используется при создании экземпляра класса для задания внутреннего состояния объекта, например:

FirstHero ourNewHero = new FirstHero("Спасти царевну");

Единственный атрибут нашего класса quest имеет тип строка (String). Для установки значения атрибута quest используется метод setQuest. Метод setQuest является public и не возвращает никакого значения. Для обозначения методов, не возвращающих значение, используется зарезервированное слово void. Для вызова метода setQuest необходим обязательный параметр: Quest типа String. Для получения значения атрибута quest используется метод getQuest, который вызывается без параметров, является открытым и возвращает значение типа String.

Вызов описанных выше методов для объекта ourNewHero осуществляется следующим образом:

ourNewHero.getQuest();
ourNewHero.setQuest("какая-то строка");

Парные методы, различающиеся приставками set и get, принято создавать для работы с закрытыми атрибутами. Это обязательное условие для реализации объекта в виде JavaBean. Что такое JavaBean, мы обсудим позже – сейчас запомните, что такое наименование методов позволяет избавиться от ряда проблем в больших системах.

Приступим к написанию самой сказки. Возьмите следующий код и поместите его в файл Story.java.

public class Story {
  public static void main(String[] args) {
    FirstHero ourNewHero = new FirstHero("Спасти царевну ");
    System.out.println("Наш герой хочет отправиться в путь и " + ourNewHero.getQuest());
  }
}

Это класс Story, он имеет всего один метод main, который является статичным (static-методы и переменные принято называть переменными класса и методами класса, т.к. они общие для всех объектов) и используется для работы с классом в целом. Метод main – это стартовая точка для запуска программы, с которой начинается интерпретация кода.

В ходе интерпретации метода main создается новый объект ourNewHero, а также вызывается метод println объекта out, который обеспечивает вывод в стандартный выходной поток строковойпеременной.

Откомпилируем код и увидим, что у нас получилось. Для компиляции переместитесь в каталог, где вы разместили свои файлы и выполните следующую команду:

# javac *.java

При желании вы можете откомпилировать классы по отдельности, следующим образом:

# javac Story.java
# javac FirstHero.java

В итоге вы получите два файла Story.class и FirstHero.class. Теперь посмотрим на результат:

# java Story
Наш герой хочет отправиться в квест и Спасти царевну

Первая программа на Java готова и работает! Вы создали два класса и научились выводить информацию в консоль. Но мы забыли о комментариях...

Комментарии бывают нескольких типов:

  • Строчные начинаются с символа // и длятся до окончания строки.
  • Многострочные комментарии заключаются между /* и */.
  • Комментарии JavaDoc – это многострочные комментарии, заключенные между /** и */, например:
/**
 * Класс является прототипом объекта "герой"
 * @author Chernousov Anton
 * @version 0.1
 */
public class FirstHero {/**
   * Метод предназначен для установки внутренней переменной
quest
   * в значение Quest.
   * У этого метода один параметр
   * @param Quest это переменная означает задание для Героя
   */
  public void setQuest(String Quest)

Комментарии JavaDoc предназначены для формирования документации к проекту из исходных кодов. Если добавить в файл FirstHero.java только что приведенные строки, то с помощью команды javadoc -author -version *.java можно сформировать документацию к нашему проекту.

JavaDoc позволяет создавать подробную документацию, которая просто необходима для любого достаточно крупного проекта.

Наследование, интерфейсы и их реализация

Наша сказка написана, но что делать, если проект большой и над ним работает много людей? Как реализовать одновременное программирование разных классов так, чтобы результаты, полученные отдельными разработчиками, можно было без труда соединить в единое целое? Для решения этой задачи, а также задачи множественного наследования в Java существуют интерфейсы – interface. Но обо всем по порядку.

Наследование – это одна из парадигм программирования, которая связана с инкапсуляцией. Суть наследования заключается в следующем: если есть класс, инкапсулирующий в себе некоторые атрибуты и методы, то класс, наследующий его, автоматически наследует все его атрибуты и методы.

public class SecondHero extends FirstHero{
  public SecondHero(String Quest) {
    super(Quest + " Несмеяну");
  }
}

Расположенный выше код объявляет класс SecondHero, который с помощью зарезервированного слова extends наследует (расширяет) класс FirstHero. В Java класс может наследовать (расширять)только один класс. При наследовании класса FirstHero, содержащего конструктор, обязательно требуется переопределить его (например, как это делается в методе SecondHero). При выполнении оператора super(Quest) будет вызван аналогичный метод из суперкласса (класс-родителя). Строкой super(Quest + "Несмеяну") мы переопределяем поведение конструктора. Естественно, класс SecondHero может содержать новые атрибуты и методы.

Для проверки механизма наследования сохраните приведенный текст класса SecondHero в файл SecondHero.java и в файле Story.java измените имя класса FirstHero на SecondHero. Откомпилируйте и запустите программу, в результате вы должны увидеть следующее:

# java Story
Наш герой хочет отправиться в путь и Спасти царевну Несмеяну

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

Интерфейс в Java – это специальный класс, в котором отсутствует реализация! Давайте напишем интерфейс для нашего класса FirstHero. Следует скопировать следующий далее код и поместить его в файл Hero.java – именно этот интерфейс мы будет использован далее. Как вы видите, в отличие от других классов, интерфейс объявляется с помощью зарезервированного слова interface. В нашем случае интерфейс представляет собой следующий набор методов:

public interface Hero {
  public void setQuest(String Quest);
  public String getQuest();
}

Чтобы класс FirstHero реализовывал интерфейс Hero, необходимо изменить первую строчку в файле FirstHero.java на public class FirstHero implements Hero {. Интерфейс может наследовать (расширять) множество других интерфейсов. Наример:

public interface Lord {
  public String sendToQuest();
  public void setBodyguard(Hero hisHero);
  public Hero getBodyguard();
}
 
public interface King extends Hero, Lord{
  public void setWife (String PrincesName);
  public String getWife();
}

Класс может одновременно наследовать класс и реализовывать один или несколько интерфейсов. Например, как в классе LandLord, который наследует класс FirstHero и реализует интерфейс Lord:

public class LandLord extends FirstHero implements Lord{
  private Hero bodyguard;
  public LandLord(String Quest, Hero hisHero) {
    super(Quest);
    this.bodyguard = hisHero;
  }
  public String sendToQuest() {
    bodyguard.setQuest(this.getQuest());
    return null;
  }
  public void setBodyguard(Hero hisHero) {
    this.bodyguard = hisHero;
  }
  public Hero getBodyguard() {
    return bodyguard;
  }
}

Чтобы окончательно закрыть тему наследования, необходимо поговорить про абстрактные классы – те, что занимают промежуточное место между интерфейсами и реальными классами. Объявление абстрактного класса или метода выполняется с помощью специального слова abstract:

abstract public class Knight

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

Полиморфизм

Полиморфизм – это концепция, реализованная в Java, которая позволяет одному и тому же объекту выступать в разных формах. Например, экземпляр класс LandLord можно использовать как объект класса FirstHero. Это стало возможным благодаря тому, что класс LandLord наследует класса FirstHero.

Перегруженные методы

Иногда при создании сложных (и не очень) систем есть необходимость реализовать два различных метода, названых одинаково – это возможно с помощью перегруженных (overloading) методов. Выбор реализации зависит от типа объектов, переданных в качестве параметров.

public class GreatKing extends LandLord implements King{
  private String wife;
  private boolean theftedWife;
 
  public GreatKing(String Quest, Hero hisHero) {
    super(Quest, hisHero);
  }
 
  public void setWife(String PrincesName) {
    this.wife = PrincesName;
    this.theftedWife = false;
  }
 
  public String getWife() {
    if (theftedWife){return null;}
    else{ return wife;}
  }
 
  public String getWife(boolean flag) {
    if (flag){ this.theftedWife = true;}
    return wife;
  }
}

В представленном классе GreatKing существуют две реализации перезагруженного метода getWife, которые можно вызвать следующим образом:

GreatKing ourKing = new GreatKing("Править мудро", (Hero) new FirstHero("Охранять господина"));
String hisWife = ourKing.getWife();
String theftedHisWife = ourKing.getWife(true);

Вместо заключения

Ну вот, мы создали всех героев. Разместите интерфейсы Lord, King, а также классы LandLord и GreatKing в соответствующих файлах. Немного измените класс Story, чтобы завершить сказку:

public class Story {
  public static void main(String[] args) {
    // создадим наших героев
    Hero ourNewHero = (Hero) new FirstHero("Спасити царевну");
    GreatKing ourKing = new GreatKing("Править мудро", (Hero) new FirstHero("Охранять господина"));
    LandLord ourNewLandLord = new LandLord("Похитить царевну", (Hero) new FirstHero("Охранять господина"));
    // Женим нашего короля
    ourKing.setWife("Несмеяна");
    // И начнем повествование
    System.out.println("Жил был мудрый король, и должен был он " + ourKing.getQuest());
    System.out.println("Была у него жена, и звали ее " + ourKing.getWife());
    System.out.println("Был в королевстве коварный Визирь и хотел он " + ourNewLandLord.getQuest());
    System.out.println("И сделал это");
    String wife = ourKing.getWife(true);
    //
    System.out.println("А наш герой жаждал " + ourNewHero.getQuest() + " ..и добился этого");
    ourKing.setWife(wife);
    System.out.println("Король был счастлив.");
    System.out.println("Ну а что случилось дальше вы можете придумать сами...");
  }
}

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

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

Персональные инструменты
купить
подписаться
Яндекс.Метрика