Всего на сайте:
236 тыс. 713 статей

Главная | Информатика

Основные свойства объектно-ориентированного подхода  Просмотрен 593

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

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

Синтаксис:

class B extends A { . . . // тело класса B}

Внутри записываются "дополнения и изменения", вносимые классом B. Класс A называют базовым классом или суперклассом, B - классом-потомком. В свою очередь, класс A может быть порожден на базе другого класса, тогда этот класс является предком как для A, так и для B. От одного класса может быть порождено произвольное количество новых классов. В результате получается иерархия классов, порожденных один от другого.

Рассмотрим пример (наследование полей)

class Base { int a, b, c; . . .} class Derived extends Base { long d, e; . . .}

Объекты класса Base имеют три поля (a, b и c), объекты класса Derived - пять полей (a, b, c, d и e).

Пример (наследование методов)

class Base { int f() { . . .
} void g(int p) { . . . }} class Derived extends Base { long f1() { . . . }}

Класс Base имеет два метода (f() и g(...)), класс Derived - три метода (f(), g(...) и f1()).

Пример (переопределение методов)

class Base { int f() { . . . } void g(int p) {. . .}}class Derived extends Base { int f() { . . . }}

Класс Base имеет два метода (f() и g(...)) и класс Derived тоже имеет два метода (f() и g(...)). Но для объектов класса Derived будет вызываться не метод f() из Base, а метод f() из Derived. При переопределении метод в порожденном классе должен иметь в точности то же описание, что и метод в базовом классе. В частности, попытка описать "long f()..." или даже "private int f()..." привела бы к ошибке при трансляции программы.

В Java фактически все классы строятся на базе наследования, т.к., даже если не написать "extends имя_класса", будет подразумеваться extends Object. Т.е. класс Object является базовым классом для всех классов Java. Класс Object имеет ряд методов, при наследовании методы базового класса наследуются его потомками. Следовательно, все классы Java имеют как минимум те методы, которые есть в классе Object.

Классы потомки могут наследовать от родительских классов только поля и методы, но не могут наследовать конструкторы.

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

Пример

class X { X(int a) { ... } ...}class Y extends X { Y() { super(0); ... } ... }

Ключевое слово super может использоваться и для явного вызова методов базового класса. Это необходимо, если некоторый метод базового класса был переопределен в порожденном классе.

Пример

class Base { int x = 1; long y; Base(long y) { this.y = y; } Base() { this(0); // вызов конструктора Base(long y) } public long f() { return x*y; }} class Derived extends Base { String name = ""; Derived(String name, long par) { super(par); // вызов конструктора Base(long y) this.name = name; } public long g(int r) { return r+super.f();// вызов метода f() класса Base } public long f() { x++; return 2*y; }}

Рассмотрим подробно, из каких полей и методов состоит класс Derived. Из класса Base в него вошли поля x и y и метод f(). Плюс в нем определено поле name и методы g(...) и f(), причем метод f() переопределяет одноименный метод класса Base.

В нашем примере, в методе g(...), требуется вызвать не метод f() класса Derived, а метод f() класса Base. При этом применяется ключевое слово super. Без него вызвался бы метод f() класса Derived.

В ООП применяется понятие полиморфизм .

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

Понятие полиморфизма, в свою очередь, опирается на два других понятия: совместное использование ( или перегрузка) и переопределение.

Рассмотрим их подробнее.

Под совместным использованием понимают использование одноименных методов с различным набором параметров. При вызове метода в зависимости от набора параметров выбирается требуемый метод. При этом одноименные методы могут быть как в составе одного класса, так и в разных классах, связанных отношением наследования. Это статический полиморфизм методов классов. Примеры совместного использования мы уже встречали ранее. Приведем еще несколько примеров.

class X { int f() { . . . } void f(int k) { . . . }...}

В классе X есть два метода f(...), но с разными типами возвращаемого значения и разными наборами параметров. Тип возвращаемого значения не является определяющим фактором при совместном использовании — при вызове метода транслятору нужно определить, какой из одноименных методов вызывать, а тип возвращаемого значения, в общем случае, не позволяет сделать это однозначно.

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

class Base { int f(int k) { . . . } . . .} class Derived extends Base { int f(String s, int k) { . . . } . . .}

В данном примере представлено совместное использование при наследовании. Класс Derived имеет два метода f(...). Один он наследует от класса Base, другой описан в самом классе Derived.

Рассмотрим пример перегрузки методов в апплете :

// OverloadShowMessage.java 1 import java.awt.*;2 import java.applet.*;3 public class OverloadShowMessage extends Applet{ 4 void ShowMessage(Graphics d, String Message ){5 d.drawString(Message,5,15);6 } 7 void ShowMessage(Graphics d,String first,String second){8 d.drawString(first+second,5,30);9 } 10 public void paint(Graphics g){11 ShowMessage(g,"Java Now!");12 ShowMessage(g,"Java Now!", " is really easy");13 }14 }

 

Рис.11.1 Окно апплета

В данном апплете перегружается метод ShowMessage. В процессе компиляции компилятор сам определяет какой из методов необходимо вызвать - в зависимости от набора параметров. После запуска апплета, его окно будет выглядеть, как на рис. 11. 1.

При переопределении методов речь идет только о паре классов — базовом и порожденном. В порожденном классе определяется метод полностью идентичный как по имени, так и по набору параметров тому, что есть в базовом. Это — динамический полиморфизм методов.

Пример

class A { int x; int f(int a) { return a+x; } . . .} class B extends A { int y; int f(int s) { return s*x; } . . .}
Предыдущая статья:Клас Math.. Среди других встроенных классов отметим класс Math. Методи класу Math.. Следующая статья:Интерфейсы. Понятие интерфейса чем-то похоже на абстрактный класс. Интерфейс — это..
page speed (0.0108 sec, direct)