Figure Class public abstract class Figure { private int x; private int y; protected String msg = "I am "; // обычно, еще конструкторы, accessors, // и mutators // abstract draw method public abstract void draw(int x, int y); } Все классы в иерархии будут иметь координаты (x, y) и цвет. Подкласс будет реализовать метод draw. Абстрактный класс не содержит реализации метод. Пример полиморфизма Предположим есть класс FigureClient. Этот класс использует классы справа для представления фигур. (предполагается, что они находятся в одном и том же пакете) public class Circle extends Figure { @Override public class FigureClient public void draw(int x, int y) { // TODO Auto-generated method stub { System.out.println(msg+"Circle with centre "+x+" public static void main ( String [] rags) "+y); } { Circle circle=new Circle(); Square square=new Square(); Figure figure; //только объявление объекта, не создается экземпляр объекта figure=circle; // переменная ссылается на окружность figure.draw(); // и будет сообщение окружности figure=square; // переменная ссылается на квадрат figure.draw(); // будет сообщение квадрат. } public class Square extends Figure { @Override public void draw(int x, int y) { // TODO Auto-generated method stub System.out.println(msg+"Square"+" with sides "+x+" "+y); } } …………………………………………………………… …………………… Абстрактный (Abstract) класс 3 Родительский (Parent) класс, экземпляр которого не может быть создан непосредственно, поскольку у него имеется по крайней мере одна абстрактная операция (abstract operation) . Только подклассы родительского абстрактного класса могут быть материализованы. Абстрактный класс в UML выделяется курсивом. public abstract class VideoMedium { public abstract Double rentalCharge(); } public class VideoDisk extends VideoMedium { public VideoDisk() {...} public Double rentalCharge() { return null; } } Interface Именованный набор общедоступных поведений и/или элементов постоянных данных, для которых класс, реализующий этот интерфейс, должен предоставить код. Он не указывает детали поведения, но перечисляет. В сущности (и для Javaкомпилятора), интерфейс определяет новый тип данных и является одним из наиболее мощных средств языка. Другие классы реализуют интерфейс; это означает, что они могут использовать любые константы этого интерфейса по имени, и что они должны реализовывать поведение для определений методов в интерфейсе. Любой класс в любой иерархии может реализовать конкретный интерфейс. Это означает, что другие, несвязанные классы могут реализовать этот же самый интерфейс. Interface Описание public interface interfaceName { final constantType constantName = constantValue; ...... returnValueType methodName ( arguments ); ...... } Использование public class className extends superclassName implements interfaceName, ... { <class body> } Простой пример интерфейса public interface Average{ public int[] getInts(); public void setInts(); public float getAverage(); } Простой интерфейс и любой класс должен реализовать методы getInts, setInts, getAverage. Естественно, что методы внутри класса реализации должен иметь те же самые аргументы. Типичное использование абстрактных классов и интерфейсов Когда необходимо обеспечить шаблон для серии подклассов, каждый из которых может (должен) наследовать некоторую функциональность из родительского класса , но требуется реализовать некоторые из них самостоятельно. Когда требуется реализовать некоторые общие для разных объектов функции, используется абстрактный класс. Абстрактный класс поддерживает только одну реализацию, т.е. каждый класс может расширять только один абстрактный класс (extends – один класс) Типичное использование абстрактных классов и интерфейсов Подкласс применяется всякий раз, когда вы хотите расширить класс и добавить некоторые функции в нем, не важно является родительский класс абстрактным или нет. Подкласс применяется, когда вы обязаны расширять данный класс . Апплеты, сервлеты и другие используют подклассы, чтобы обеспечить "основу" функциональности в классах, которые динамически загружаются. Определять интерфейс, когда нет общего родительского класса с требуемой функциональностью и когда вы используете только определенные несвязанные классы, имеющие некоторую функциональность Типичное использование абстрактных классов и интерфейсов Когда требуется реализовать некоторые общие для разных объектов функции, используется абстрактный класс. Абстрактный класс поддерживает только одну реализацию. Интерфейсов может быть реализовано несколько. Когда требуется указать некоторый перечень возможностей объекта, используется интерфейс Перегружаемые методы Возможность приписывать разную функциональность одному методу (функции, операции) называется перегрузкой метода (функций, операций) Перегруженные методы - это методы, которые находятся в том же самом классе и имеют то же самое имя, но различные списки параметров. Пример перезагруженного метода Структура объекта Java (БНФ) package packageName; import ClassNameToImport; accessSpecifier class ClassName { /* объявление класса */ accessSpecifier dataType variableName [= initialValue]; accessSpecifier ClassName([argumentList]) { Утверждения конструктора } accessSpecifier returnType methodName([argumentList]) { Утверждения метода } // Комментарий /* Тоже комментарий */ /* Это комментарий несколько строк строк */ /** Это комментарий для создания документации в формате html с помощью программы javadoc из JDK* / Объявление класса Для использования класса его необходимо предварительно объявить Класс является образцом (шаблоном) объекта, и определяет структуру объекта, в соответствии с которой во время выполнения создается и применяется экземпляр объекта Слово object является синонимом слова class Строго говоря, class определяет структуру вещей, экземплярами которых являются object Пакеты объектов Как мы говорили для устранения коллизии (двусмысленности) имен в Java используются пакеты (package), что является механизмом обеспечения пространства именования (namespace), т.е. определения области, в которой имена являются уникальными. Необходимо полностью квалифицировать конструкции языка, включая его namespace Обеспечивается также хорошая возможность формирования сложного приложения в рамках компонентов. Упрощается поиск классов в функциональных группах (пакетах) Например, com.application.dao – пакет содержит классы для обеспечения ввода-вывода c БД Определение Package Используется ключевое слово package с действительным именем пакета, завершающееся «;» Часто имена пакетов разделяются точкой и следуют по де-факто схеме: package orgType.orgName.appName.compName; package com.company.customer; Фактически можно обойтись без образования пакетов, если обеспечивается уникальность имен в пакете по умолчанию. Утверждение Import Утверждение import сообщает компилятору Java где найти классы, на которые ссылаются в коде. Утверждение обычно выглядит следующим образом: import ClassNameToImport; Для импорта всех классов внутри пакета можно использовать * после имени пакета, например import com. ogroup.*; import java.math.BigDecimal; import java.util.Locale; Eclipse упрощает импорт Редактор Eclipse при написании кода позволяет ввести имя класса и затем Ctrl+Shift+O Объявление класса accessSpecifier class ClassName { accessSpecifier dataType variableName [= initialValue]; accessSpecifier ClassName([argumentList]) { constructorStatement(s) } accessSpecifier returnType methodName([argumentList]) { methodStatement(s) } } accessSpecifier может иметь несколько значений, но чаще всего public или private. Классы могут именоваться произвольно, но используются соглашения CamelCase: начинается с заглавной буквы, также с заглавной буквы начинается каждое слово в составном имени . (CustomerDriver) Имя класса должно состоять из букв и чисел. Классы содержат два типа элементов: переменные (variables) и методы (methods). AccessSpecifier-спецификаторы доступа public: Любой объект в любом пакете «видит» (может обращаться) переменную. (Никогда не используйте это значение-опасно для жизни приложения) protected: Любой объект, определенный в этом же пакете или подклассе (определенный в любом пакете) может видеть переменную. Не специфицированное (также называется friendly или package private access): только объекты классов, определенных в том же пакете могут видеть переменную. private: только класс, содержащий переменную, может «видеть» ее. Определение Class для Person package com.group.intro; public class Person { private String name; private int age; private int height; private int weight; private String eyeColor; private String gender; } Методы Методы класса определяют его поведение. Иногда такое поведение не делает ничего более кроме возвращение текущих значений атрибутов. Иногда поведение может быть достаточно или исключительно сложным. Существует две категории методов: Конструкторы (constructors)-используются только для создания экземпляров класса Все другие методы, которые могут быть потенциально использованы в поведении любого приложения. Methods accessSpecifier returnType methodName([argumentList]) { • Имя метода methodStatement(s) • Количество аргументов • Типы аргументов } • Порядок аргументов Комбинация структурных элементов в определении методов называется сигнатура (signature.). Синтаксис конструктора: accessSpecifier ClassName([argumentList]) { constructorStatement(s) }// Имя конструктора должно совпадать с именем класса и конструктор не должен возвращать данные Если конструктор не создается, то компилятор автоматически вставит его без параметров. Иногда для конструкторов необходимо указывать список аргументов, состоящий из одного или более argumentType argumentName (список через ,) Определение Class с constructor public class Person { private String name; private int age; private int height; private int weight; private String eyeColor; private String gender; public Person() { } public Person(String name, int age, int height, int weight, String eyeColor, String gender) { this.name = name; this.age = age; This.height = height; this.weight = weight; this.eyeColor = eyeColor; This.gender = gender; } } this является сокращением "this object" и должно быть использовано когда ссылаются на две переменных с одним и тем же именем и помогает компилятору устранять неоднозначность ссылки. Объект Person становится более интересным, если он получает Другие методы Ряд других методов, отличных от конструктора, выполняют различные функции в программе Java. В отличие от конструктора имена других методов не должны совпадать и могут называться произвольно. Методы часто имеют возвращаемый тип в отличие от конструкторов, которые не должны этого делать Именование методов : Начинаются со строчного символа Не используют специальные символы accessSpecifier returnType methodName([argumentList]) { methodStatement }_________________________________________________ public String getName() { return name; } public void setName(String value) { name = value; } // Другие комбинации getter/setter Методы: Static и экземпляра класса Методы экземпляра (Instance method) зависят от состояния экземпляра объекта (значения его полей) для выполнения их поведения. Методы Static иногда называются методами класса, поскольку их поведение не зависит от состояния любого одиночного объекта и поведение определяется на уровне класса. Статический метод аналогичен global в С . Класс Math содержит множество методов для часто встречающихся математических операций. Эти методы объявлены статическими, так как они работают не с каким-то определенным объектом, но составляют внутри класса группу со сходными функциями. dataType может быть либо primitive либо ссылкой на другой объект. Например, Age - int (primitive), а Name String (object). JDK доступен с полным набором полезных классов , например, пакеты java.lang.String и java.lang нет необходимости импортировать поскольку они всегда используются компилятором Java по умолчанию, остальные следует импортировать.). Вне зависимости от того, является ли dataType JDK – тип системы программирования (как, например, String, Date, Scanner, …) или класс определяется разработчиком, синтаксис абсолютно одинаков. Расширение поведения Класс Person, который мы создавали, выполняет свои обязанности, однако если их расширить (добавить функциональности классу), то класс стал бы более интересным. Расширение обязанностей класса – добавление методов. Рассмотрим более подробно методы accessor именно getters и setters мы видели в действии. Рассмотрим синтаксис для вызова методов. Методы Accessor Для инкапсуляции данных классов от других объектов переменные объявляются private и затем обеспечиваются методы accessor: getter методы для получения значений атрибутов, setter методы для модификации значений атрибутов. Именование этих методов известно как JavaBeans pattern (шаблон), в котором Foo имеет getter с именем getFoo(), а setter называется setFoo(). Foo – используются для обозначения сущностей, также как переменные, функции и команды, цель которого не имеет значения и служат лишь для демонстрации Правила создания accessor Именование этих методов известно как JavaBeans шаблон и, в принципе, определяет и другие понятия (напр. События) Атрибут всегда объявляется private доступом. access specifier для getters и setters должен быть public. Getters не принимает параметров и возвращает значение соответствующего типа getFoo(). Setter принимает только один параметр типа атрибута и не возвращает значения setFoo(<аргумент>). Для переменных типа boolean имена обозначаются: isFoo() и setFoo(<аргумент>), соответственно private String foo; public String getFoo() { return foo; } public void setFoo(String value) { foo = value; } Вызов методов Для вызова метода объекта необходимо сослаться на этот объект и после точки указать имя метода и параметры, которые должны быть переданы. objectReference.someMethod(); objectReference.someOtherMethod(parameter); Ниже примеры вызова: Person p = /*получен любым способом*/; p.getName(); Person p = new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE"); Вспомним, конструкторы - тоже методы. Можно отделять параметры пробелами и переводом сроки, на что компилятор не обращает внимания. new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE"); new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE"); Конструкторы Часто требуется, чтобы при создании объекта все) переменные реализации 33 некоторые (или были автоматически инициализированы в соответствии с заданными значениями. Это можно сделать с помощью метода специального типа, именуемого конструктор. Конструктор (constructor) — это метод, который вызывается в момент создания нового объекта. Конструктор может выполнять любое действие, которое имеется в его определении, но основное назначение конструкторов - выполнение некоторых действий инициализации, например, инициализации значений переменных экземпляра класса (реализации). Конструкторы 34 Назначение конструкторов во многом совпадает с назначением методов set при определении класса Но в отличие от методов set, конструкторы вызываются при создании объекта с помощью оператора new. Еще раз! Конструкторы (методы) имеют то же самое имя, что и сам класс При определении конструктора не требуется указывать тип возвращаемого значения, и void также опускается. Конструкторы - пример 35 public static void main (String [] arg) { PetRecord cow = new PetRecord ("Qween" ,10, 400); … PetRecord fish = new PetRecord("Titanic", 2, 0.2); …. PetRecord newBorn= new PetRecord(); …. } Конструкторы -резюме 36 Конструктор — это прежде всего метод, который вызывается при создании объекта класса с помощью оператора new. Конструкторы используются для инициализации внутреннего состояния объектов. Имя конструктора должно совпадать с именем класса, которому он принадлежит. Вызов конструктора, например, new PetRecord () возвращает ссылку на объект, т.е. он возвращает адрес памяти, выделенной объекту. Конструкторы (зачем) 37 Некоторые классы не обладают разумным начальным состоянием, если не инициировать значения переменных реализации. При конструировании объектов некоторых видов передача исходного состояния оказывается самым удобным и естественным способом. Конструирование объектов потенциально сопряжено с большими накладными расходами, поэтому желательно при создании объекта сразу устанавливать правильное исходное состояние. Например, если каждый объект класса содержит таблицу, то конструктор, получающий исходный размер таблицы в качестве параметра, позволит с самого начала создать объект с таблицей нужного размера. Конструкторы (зачем) 38 Конструктор, атрибут доступа которого отличается от public, ограничивает возможности создания объектов данного класса. Можно запретить, например, программистам, работающим с созданным вами пакетом, расширять тот или иной класс, если сделать все конструкторы доступными лишь из пакета (default). Кроме того, можно пометить ключевым словом protected те конструкторы, которые предназначены для использования исключительно в подклассах. Конструкторы 39 Если не объявлять для класса никаких конструкторов, то Java создает безаргументный конструктор по умолчанию. Этот конструктор создается автоматически лишь в тех случаях, когда нет никаких других конструкторов и он инициализирует все поля нулями (null для объектов). Конструкторы 40 } Если безаргументный конструктор должен существовать наряду с одним или несколькими конструкторами, использующими аргументы, можно определить его явно . class SimpleClass { / * * Эквивалент конструктора по умолчанию * / public SimpleClass () { …. } Статические методы и переменные 41 При вызове статического метода вместо использования имени объекта обычно используется имя класса, в котором этот метод определен. Статические методы иногда называются методами класса (class methods), они вызываются для целого класса, а не для каждого конкретного объекта, созданного на его основе. Статические методы и переменные 42 Статические методы и переменные Ограничения по использованию 43 Если класс содержит переменные реализации, то к ним нельзя обращаться в утверждениях статических методов (по-русски-в статическом методе нельзя обращаться к переменным объектов) Внутри определения любого статического метода нельзя вызывать нестатический метод (если не создать новый объект этого класса, а затем использовать этот объект в качестве объекта для вызова нестатического метода) B определении статического метода нельзя использовать переменную реализации или метод, который имеет явно или неявно заданный параметр this для вызывающего объекта. Статические методы и переменные 44 Если диаметр круга равен 2, Площадь равна 3.141592653589793 А теперь выберите сами значение диаметра. Введите диаметр круга: 45 Площадь равна 1590.431280879833 Статические методы и переменные 45 Java требует, чтобы main-метод программы был статическим. Следовательно, внутри main-метода нельзя вызвать нестатический метод того же класса, не создав объект этого класса и не задействовав его в качестве вызывающего объекта для этого нестатического метода. Каждый класс может иметь main-метод, т.е. в каждый класс можно поместить main-метод. В этом случае его (класс) можно выполнять как программу. При выполнении этого класса в качестве программы вызывается main-метод, остальная часть определения класса игнорируется. Статические методы и переменные 46 Если же класс не предназначен для использования в качестве программы, mainметод в нем все равно может иметь право на существование, если он будет представлять собой тестовую программу для этого класса (хотя обычно используется специальная тестовая технология JUnit). При использовании в качестве обычного класса для создания объектов игнорируется main-метод – т.е. это просто один из прочих методов, к которому нет обращений. Статические методы и переменные 47 Иногда возникает необходимость совместного использования переменной всеми объектами класса. Они называются переменными класса, т.е. переменными относящимися ко всему классу, в отличие от переменных, относящихся к его отдельным объектам и описываются как static ПРИМЕРЫ: private static int numberOflnvocations = 0; public static Point origin = new Point ( ); Статические методы и переменные 48 Подобно переменным реализации, статические переменные обычно объявляются закрытыми (private). Возможность чтения и изменения их значений вне класса должна предоставляться только посредством определения доступа. Статические методы и переменные 49 1 2 3 4 5 6 7 8 9 10 Общее количество вызовов = Определение классов и методов 50 В Java запрещается иметь одноименные переменные внутри одного определения метода. Переменные, объявленные в блоке, являются локальными живут только внутри блока { }) по отношению к этому блоку и исчезают, когда выполнение этого блока завершается. Блок – составной оператор с описаниями. Переменную нельзя использовать вне блока, в котором она описана. Определение классов и методов Слайд № 51 При обращении к методу формальные аргументы заменяются на фактические (реальные) параметры. Если формальные параметры имеют примитивные типы, то при замене формальных параметров на фактические используется механизм вызова по значению (call by value) Формальный параметр, используемый в определении метода, является локальной переменной, которая инициализируется значением фактического параметра. Определение классов и методов Слайд № 52 Между формальными и фактическими параметрами устанавливается взаимнооднозначное соответствие. В случае рассогласования по типу осуществляется автоматическое преобразование типов: Byte->short->int->long->float->double Определение классов и методов Слайд № 53 Параметры типа класса являются ссылками. В переменной типа класса хранится не объект этого класса, а адрес области (ссылка на объект – reference) оперативной памяти, где расположен объект Все типы классов являются ссылочными типами, но существуют также ссылочные типы, которые не являются типами классов (например, массивы) Определение классов и методов Слайд № 54 Формальные параметры типа класса обрабатываются на основе другого механизма замены (call by reference). Формальный аргумент типа класса – локальная переменная , в которой хранится адрес объекта этого класса. При обращении к методу аргумент инициализируется адресом соответствующего фактического параметра, задаваемого в вызове метода, т.е. Формальный аргумент служит в качестве альтернативного имени для объекта, заданного параметром при вызове метода Следствие: Метод способен менять значения переменных реализации аргумента, имеющего тип класса Определение классов и методов Слайд № 55 Рекурсия Java поддерживает рекурсию. Рекурсия — это процесс определения чего-то в терминах самого себя. В программировании рекурсия — это атрибут, который позволяет методу вызвать самого себя. Такой метод называют рекурсивным. Определение классов и методов // Простой пример рекурсии. class Factorial { // это рекурсивная функция int fact (int n) { int result; if (n==1) return 1; result = fact(n-l) * n; return result; } } Слайд № 56 Определение классов и методов class Recursion { public static void main (String args[]) { Factorial f = new Factorial ( ) ; System.out.println( "Факториал 3 равен " + f.fact(3)); System.out.println( "Факториал 4 равен " + f.fact (4) ) ; System.out.println( "Факториал 5 равен " + f.fact (5)); } факториал 3 равен 6 } факториал 4 равен 24 Слайд № 57 факториал 5 равен 120 Область видимости переменных Каждая переменная в Java имеет область видимости, или локализацию пространства имен, где можно получать доступ к этой переменной по ее имени из программы. Если переменная, к которой обращаются в коде по имени, находится вне области видимости, вы получаете сообщение об ошибке. Уровень видимости определяется местом в классе, где эта переменная объявлена. Variable scope диапазон Внутри класса SomeClass переменная someClassVariable доступна из всех методов (блоков). Внутри метода someMethod переменная someParameter видна, однако не public class SomeClass { доступна вне метода, аналогично в отношении переменной private String someClassVariable; public void someMethod(String someParameter) {someLocalVariable. Внутри блока if объявлена переменная String someLocalVariable = "Hello"; someOtherLocalVariable, которая за Область видимости if (true) { пределами блока не доступна. String someOtherLocalVariable = "Hollo"; } someClassVariable = someParameter; // верно переменной простирается до конца секции (или блока) кода, в котором она была объявлена. someLocalVariable = someClassVariable; // также верно someOtherLocalVariable = someLocalVariable;// Переменная не видна! } public void someOtherMethod() { someLocalVariable = "Hello there";// ;// Переменная не видна! } } Сравнение объектов Язык Java предоставляет два способа сравнения объектов: оператор ==; метод equals(). Сравнение объектов с помощью оператора == Оператор == сравнивает объекты на равенство, так что выражение a == b возвращает значение true, только если а и b имеют одно и то же значение. Для объектов это означает, что оба ссылаются на один и тот же экземпляр объекта. Для примитивов это означает, что значения идентичны. int int1 = 1; int int2 = 1; print("Q: int1 == int2? A: " + (int1 == int2)); - true Integer integer1 = Integer.valueOf(int1); Integer integer2 = Integer.valueOf(int2); print("Q: Integer1 == Integer2? A: " + (integer1 == integer2)); - true (хотя это разные объекты, но ссылаются на один и тот же экземпляр) integer1 = new Integer(int1); integer2 = new Integer(int2); print("Q: Integer1 == Integer2? A: " + (integer1 == integer2)); -false Employee employee1 = new Employee(); Employee employee2 = new Employee(); print("Q: Employee1 == Employee2? A: " + (employee1 == employee2)); -false print ("equal:Employee1.equal.Employee2? A: " + (employee1.equals(employee2))); -true Сравнение объектов с помощью equals() equals() - это метод, который каждый объект языка Java получает по определению, поскольку он определяется как метод экземпляра java.lang.Object (от которого наследует каждый объект Java) – мы с вами смотрели структуру. equals() вызывается точно так же, как любой другой метод: a.equals(b); Этот оператор вызывает метод equals() объекта а, передавая ему ссылку на объект b. По умолчанию Java-программа просто проверяет, что два объекта одинаковы, с помощью синтаксиса ==. Однако так как equals() - это метод, его можно переопределить Сравнение 63 Метод equals() и оператор == выполняют две совершенно различных проверки. Mетод equals сравнивает значения полей объектов и если два различных объекта имеют одинаковые поля, то объекты равны между собой. Логично, что два объекта Employee, если состояние этих объектов одинаково. То есть, они равны, если их атрибуты фамилия, имя, возраст – одни и те же. Оператор == сравнивает две переменные-ссылки на объекты и проверяет, указывают ли они на разные объекты или на один и тот же. Т.е. два равных объекта должны указывать на одно место в паямяти.