Добавил:
Rumpelstilzchen2018@yandex.ru Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
56
Добавлен:
25.12.2020
Размер:
836.76 Кб
Скачать

Тема №3: Реализация наследования в программах на Java

Содержание

1.Статические компоненты класса

2.Реализация наследования в программах на Java

3.Абстрактные классы и интерфейсы

4.Работа с графикой

Определение классов и объектов

Основным видом деятельности объектно-ориентированного проектирования является определение классов и объектов, которые составляют решение.

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

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

Объекты, как правило, существительные, а сервисы, которые предоставляет объект, как правило, глаголы.

Статические компоненты класса

Напомним, что статический метод может быть вызван через обращение к имени класса.

Например, способы вызвать статические методы класса Math : result = Math.sqrt(25)

Переменные - поля данных класса тоже могут быть статическими. Определение, того что метод или переменная должны быть статическим

является важным решением на этапе проектирования.

Модификатор static

Мы объявляем статические методы и переменные, используя модификатор static. Это связывает метод или переменную с классом, а не с

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

Статические переменные

Как правило, каждый объект имеет свое собственное пространство данных, но если переменная объявлена как статическая, то существует только одна копия переменной для всех объектов

private static float price;

Объем памяти для статической переменной создается при первом обращении класс. Все объекты - экземпляры класса разделяют его статические переменные. Изменение значения статической переменной в одном объекте изменяет ее значение для всех остальных объектов.

Статические методы

Class Compute3

{

public static int cube (int num)

{

return num * num * num;

}

}

Поскольку он объявлен как статический, метод может быть вызван в качестве

value = Compute3.cube(5);

Статические компоненты класса

Порядок модификаторов можно поменять местами, но по соглашению модификаторы видимости на первом месте.

Пример: метод main() является статическим.

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

Статические методы и статические переменные часто работают вместе.

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

Пример CountWord.java

public class CountWord { private String phrase; private static int count = 0;

/*Кон:создаеттруктор иинициализируетобъектCountWordв памятиувеличиваетсчетчикэкземпляровобъеков;*/

public CountWord(String str) { this.str = str;

count++;

}

/*методtoString()возвращаетобъеCountWordкстрокуак*/

public String toString() { return phrase;

}

/*методвозвращаколичествоэкземпляровсозданныхобъектов

*/ public static int getCount () { return count;

}

}

public class TesterСountWord {

public static void main (String[] args) { CountWord obj;

obj = new CountWord("Remember your school."); System.out.println (obj);

obj = new CountWord( "Don't Worry. Be Happy."); System.out.println (obj);

obj = new CountWord ("Your future is for you."); System.out.println (obj);

obj = new CountWord ("Talk is Cheap."); System.out.println (obj);

obj = new CountWord("Write Once, Run Anywhere."); System.out.println (obj);

System.out.println();

System.out.println ("Slogans created: " + CountWord.getCount());

}}

Отношения между классами

Классы в программных системах, могут иметь различные типы отношений друг с другом. Три из наиболее распространенных отношений:

Агрегация: A has-a B

Зависимость: A uses B

Наследование: A is-a B

Отношение зависимости

Зависимость существует, когда один класс зависит от другого каким-то образом, как правило, путем вызова методов другого

Хороший дизайн программы находится где-то между:

многочисленные или сложные зависимости между классами

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

класса. Метод класса может принимать объект одного и того же класса в качестве параметра. Например, метод concat() класса String принимает в качестве параметра другой объект

String str3 = str1.concat(str2);

Следующий пример определяет класс с именем Rational и будет представлять рациональное число. Рациональное число является значением, которое может быть представлено в виде отношения двух целых чисел. Некоторые методы класса Rational принимают объект Rational как параметры.

Пример RationalNumber.java

public class RationalNumber { private int numerator; private int denominator;

public RationalNumber (int numer, int denom) { if (denomпроверяемеслиделитель==0 0) //

denom = 1;

// позволяет numerator "хранить" знак if (denom < 0) {

numer = numer * -1; denom = denom * -1;

}

numerator = numer; denominator = denom; reduce();

}

public RationalNumber reciprocal () {

return new RationalNumber (denominator, numerator);

}

public String toString () { String result;

if (numerator == 0) result = "0";

else

if (denominator == 1) result = numerator + "";

else

result = numerator + "/" + denominator;

return result;

}

public int getNumerator () { return numerator;

}

public int getDenominator () { return denominator;

}

//сложениерациончисларациональнымльногочислом передкаквраметремым

public RationalNumber add (RationalNumber op2) {

int commonDenominator = denominator * op2.getDenominator(); int numerator1 = numerator * op2.getDenominator();

int numerator2 = op2.getNumerator() * denominator; int sum = numerator1 + numerator2;

return new RationalNumber (sum, commonDenominator);

}

//вычитанрационсрациональнымслаельногочислом передкаквраметремым

public RationalNumber subtract (RationalNumber op2) {

int commonDenominator = denominator * op2.getDenominator(); int numerator1 = numerator * op2.getDenominator();

int numerator2 = op2.getNumerator() * denominator; int difference = numerator1 - numerator2;

return new RationalNumber (difference, commonDenominator);

}

 

{

public RationalNumber multiply (RationalNumber op2)

int numer = numerator * op2.getNumerator();

 

int denom = denominator * op2.getDenominator();

return new RationalNumber (numer, denom);

 

}

 

 

//Делимумножениемнаперевевторациональноенутоечисло

{

public RationalNumber divide (RationalNumber op2)

return multiply (op2.reciprocal());

 

}

- результатсравнения.

 

//проверканаравенство,возвращаем

 

public boolean equals ( RationalNumber op2) {

 

return ( numerator == op2.getNumerator() &&

 

denominator == op2.getDenominator() );

}

 

 

//Уменьшаемрационачисло,декакчислительяьное,так

 

 

знаменательнаибольшийобщийделитель

{

 

private void reduce ()

 

if (numerator != 0)

{

 

int common = gcd (Math.abs(numerator), denominator); numerator = numerator / common;

denominator = denominator / common;

}

}

//Вычисляетвозвращаделительнаибольшийобщийдлядвух положительныхпараметровИспо ьзуегоритмЕклидася

private int gcd (int num1, int num2) { while (num1 != num2)

if (num1 > num2)

num1 = num1 - num2; else

num2 = num2 - num1; return num1;

}}

public class RationalTester

{

public static void main (String[] args)

{

RationalNumber r1 = new RationalNumber (6, 8); RationalNumber r2 = new RationalNumber (1, 3); RationalNumber r3, r4, r5, r6, r7; System.out.println ("First rational number: "

+ r1);

System.out.println ("Second rational number: " + r2);

if (r1.equals(r2))

System.out.println ("r1 and r2 are equal."); else

System.out.println ("r1 and r2 are NOT equal."); r3 = r1.reciprocal();

System.out.println ("The reciprocal of r1 is: " + r3); r4 = r1.add(r2);

r5 = r1.subtract(r2);

r6 = r1.multiply(r2);

r7 = r1.divide(r2); System.out.println ("r1 + r2: " + r4); System.out.println ("r1 - r2: " + r5); System.out.println ("r1 * r2: " + r6); System.out.println ("r1 / r2: " + r7);

}

}

Отношение Агрегация

Агрегация представляет собой объект, который состоит из других объектов. Поэтому агрегация является отношением между классами has-a .

Машина имеет (has a) двигатель.

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

Пример Агрегации в нотации UML

Наследование в Java

В Java, мы используем слово - расширяет extends для наследования

public class CheckingAccount extends BankAccount {

объекты нового класса получают все поля (состояния) и поведение (методы) родительского класса

Конструкторы и статические методы/поля не наследуются

По умолчанию, родит. класс для всех Object

Сила Java в том, что только один родительский класс (“единичное наследование”)

Еще один пример - реализация наследования

class BankAccount { private double myBalance;

public BankAccount() { myBalance = 0; }

public double getBalance() {return myBalance; }

}

class CheckingAccount extends BankAccount { private double myInterest;

public CheckingAccount(double interest) { this.myInterest = interest;

}

public double getInterest() {return myInterest; } public void applyInterest() { }

}

Ссылки и наследование

Ссылка на объект может ссылаться только на объект своего же класса, или на объект любого класса, связанного с ним наследованием.

Например, если класс BankAccount используется для создания класса под названием CheckingAccount, то ссылку на объект BankAccount можно использовать, чтобы ссылаться на объект CheckingAccount.

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

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

Расширяющее преобразование является наиболее полезным.

Тип объекта, на который ссылаются, а не тип ссылки, определяет, какой метод будет вызывается.

Предположим класс BankAccount имеет метод, называемый pay(), и класс CheckingAccount переопределяет его.

Теперь рассмотрим следующий вызов: account.pay();

Если account ссылается на объект BankAccount, он вызывает версию pay() для BankAccount; если он ссылается на объект CheckingAccount, то вызывается версия pay() для CheckingAccount.

Отношение “Has-a”

Отношение "Has-a” : когда один объект содержит другой, как поле

public class BankAccountManager {

private List<Account> accounts; // ...

}

Например объект BankAccountManager имеет или содержит ("has-a») List внутри себя, и таким образом использует список счетов клиентов в качестве поля класса.

Отношение “Is-a”

отношение является ("Is-a”) представляет реализацию множество возможностей;

реализуется через интерфейсы и наследование

public class CheckingAccount extends BankAccount {

// ...

}

Объект CheckingAccount является ("is-a" ) BankAccount

Таким образом, он может делать то, что BankAccount может делать он может быть заменен везде, где необходимо на BankAccount

Переменная ссылка типа BankAccount может ссылаться на объект CheckingAccount

Пример с банковскими счетами

CheckingAccount наследует методы BankAccount

CheckingAccount c = new CheckingAccount(0.10);

System.out.println(c.getBalance());

c.applyInterest();

Переменная BankAccount может ссылаться на объект CheckingAccount

BankAccount b2 = new CheckingAccount(0.06);

System.out.println(b2.getBalance());

Переменная Object может указывать на любой тип счета клиента BankAccount так и CheckingAccount

Object o = new BankAccount();

Object o2 = new CheckingAccount(0.09);

Код, который не компилируется

Переменная CheckingAccount не может ссылаться на BankAccount

(не каждый BankAccount "is-a" CheckingAccount)

CheckingAccount c = new BankAccount();

Мы не можем вызвать метод CheckingAccount для переменной типа BankAccount (может только использовать поведение BankAccount)

BankAccount b = new CheckingAccount(0.10);

b.applyInterest();

Мы не можем переносить поведение счета на переменную типа Object

Object o = new CheckingAccount(0.06);

System.out.println(o.getBalance());

o.applyInterest();

Принцип Наследование

Свойства системы, позволяющие описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником, дочерним или производным классом. Общие свойства и методы объектов можно вынести в класс-«родитель». Все «дети»- наследники автоматически получают их.

Пример: Домашние животные -схема наследования

Пример: класс Домашнее животное

public class Pet { private String name; private int age;

public Pet() { this("Unnamed");}

public Pet(String name) {name = "Unnamed";} public Pet(String name, int age) {

this.name = name; this.age = age;

Соседние файлы в папке Лекции