Ћекции.ќрг


ѕоиск:




 атегории:

јстрономи€
Ѕиологи€
√еографи€
ƒругие €зыки
»нтернет
»нформатика
»стори€
 ультура
Ћитература
Ћогика
ћатематика
ћедицина
ћеханика
ќхрана труда
ѕедагогика
ѕолитика
ѕраво
ѕсихологи€
–елиги€
–иторика
—оциологи€
—порт
—троительство
“ехнологи€
“ранспорт
‘изика
‘илософи€
‘инансы
’ими€
Ёкологи€
Ёкономика
Ёлектроника

 

 

 

 


—татическое и динамическое св€зывание методов. ѕолиморфизм




ƒанный параграф, несмотр€ на краткость, €вл€етс€ очень важным Ц практически всЄ профессиональное программирование в Java основано на использовании полиморфизма. ¬ то же врем€ эта тема €вл€етс€ одной из наиболее сложной дл€ понимани€ учащимис€. ѕоэтому рекомендуетс€ внимательно перечитать этот параграф несколько раз.

ћетоды классов помечаютс€ модификатором static не случайно Ц дл€ них при компил€ции программного кода действует статическое св€зывание. Ёто значит, что в контексте какого класса указано им€ метода в исходном коде, на метод того класса в скомпилированном коде и ставитс€ ссылка. “о есть осуществл€етс€ св€зывание имени метода в месте вызова с исполн€емым кодом этого метода. »ногда статическое св€зывание называют ранним св€зыванием, так как оно происходит на этапе компил€ции программы. —татическое св€зывание в Java используетс€ ещЄ в одном случае Ц когда класс объ€влен с модификатором final (УфинальныйФ, УокончательныйФ),

ћетоды объектов в Java €вл€ютс€ динамическими, то есть дл€ них действует динамическое св€зывание. ќно происходит на этапе выполнени€ программы непосредственно во врем€ вызова метода, причЄм на этапе написани€ данного метода заранее неизвестно, из какого класса будет проведЄн вызов. Ёто определ€етс€ типом объекта, дл€ которого работает данный код - какому классу принадлежит объект, из того класса вызываетс€ метод. “акое св€зывание происходит гораздо позже того, как был скомпилирован код метода. ѕоэтому такой тип св€зывани€ часто называют поздним св€зыванием.

ѕрограммный код, основанный на вызове динамических методов, обладает свойством полиморфизма Ц один и тот же код работает по-разному в зависимости от того, объект какого типа его вызывает, но делает одни и те же вещи на уровне абстракции, относ€щейс€ к исходному коду метода.

ƒл€ по€снени€ этих не очень пон€тных при первом чтении слов рассмотрим пример из предыдущего параграфа Ц работу метода moveTo. Ќеопытным программистам кажетс€, что этот метод следует переопредел€ть в каждом классе-наследнике. Ёто действительно можно сделать, и всЄ будет правильно работать. Ќо такой код будет крайне избыточным Ц ведь реализаци€ метода будет во всех классах-наследниках Figure совершенно одинаковой:

 

public void moveTo(int x, int y){

hide();

x=this.x;

y=this.y;

show();

};

 

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

≈щЄ часто вызывает недоумение, зачем в абстрактном классе Figure писать реализацию данного метода. ¬едь используемые в нЄм вызовы методов hide и show, на первый взгл€д, должны быть вызовами абстрактных методов Ц то есть, кажетс€, вообще не могут работать!

Ќо методы hide и show €вл€ютс€ динамическими, а это, как мы уже знаем, означает, что св€зывание имени метода и его исполн€емого кода производитс€ на этапе выполнени€ программы. ѕоэтому то, что данные методы указаны в контексте класса Figure, вовсе не означает, что они будут вызыватьс€ из класса Figure! Ѕолее того, можно гарантировать, что методы hide и show никогда не будут вызыватьс€ из этого класса. ѕусть у нас имеютс€ переменные dot1 типа Dot и circle1 типа Circle, и им назначены ссылки на объекты соответствующих типов. –ассмотрим, как поведут себ€ вызовы dot1.moveTo(x1,y1) и circle1.moveTo(x2,y2).

ѕри вызове dot1.moveTo(x1,y1) происходит вызов из класса Figure метода moveTo. ƒействительно, этот метод в классе Dot не переопределЄн, а значит, он наследуетс€ из Figure. ¬ методе moveTo первый оператор Ц вызов динамического метода hide. –еализаци€ этого метода берЄтс€ из того класса, экземпл€ром которого €вл€етс€ объект dot1, вызывающий данный метод. “о есть из класса Dot. “аким образом, скрываетс€ точка. «атем идет изменение координат объекта, после чего вызываетс€ динамический метод show. –еализаци€ этого метода берЄтс€ из того класса, экземпл€ром которого €вл€етс€ объект dot1, вызывающий данный метод. “о есть из класса Dot. “аким образом, на новом месте показываетс€ точка.

ƒл€ вызова circle1.moveTo(x2,y2) всЄ абсолютно аналогично Ц динамические методы hide и show вызываютс€ из того класса, экземпл€ром которого €вл€етс€ объект circle1, то есть из класса Circle. “аким образом, скрываетс€ на старом месте и показываетс€ на новом именно окружность.

“о есть если объект €вл€етс€ точкой, перемещаетс€ точка. ј если объект €вл€етс€ окружностью - перемещаетс€ окружность. Ѕолее того, если когда-нибудь кто-нибудь напишет, например, класс Ellipse, €вл€ющийс€ наследником Circle, и создаст объект Ellipse ellipse=new Ellipse(Е), то вызов ellipse.moveTo(Е) приведЄт к перемещению на новое место эллипса. » происходить это будет в соответствии с тем, каким образом в классе Ellipse реализуют методы hide и show. «аметим, что работать будет давным-давно скомпилированный полиморфный код класса Figure. ѕолиморфизм обеспечиваетс€ тем, что ссылки на эти методы в код метода moveTo в момент компил€ции не став€тс€ Ц они настраиваютс€ на методы с такими именами из класса вызывающего объекта непосредственно в момент вызова метода moveTo.

¬ объектно-ориентированных €зыках программировани€ различают две разновидности динамических методов Ц собственно динамические и виртуальные. ѕо принципу работы они совершенно аналогичны и отличаютс€ только особенност€ми реализации. ¬ызов виртуальных методов быстрее. ¬ызов динамических медленнее, но служебна€ таблица динамических методов (DMT Ц Dynamic Methods Table) занимает чуть меньше пам€ти, чем таблица виртуальных методов (VMT Ц Virtual Methods Table).

ћожет показатьс€, что вызовы динамических методов неэффективен с точки зрени€ затрат по времени из-за длительности поиска имЄн. Ќа самом деле во врем€ вызова поиска имЄн не делаетс€, а используетс€ гораздо более быстрый механизм, использующий упом€нутую таблицу виртуальных (динамических) методов. Ќо мы на особенност€х реализации этих таблиц останавливатьс€ не будем, так как в Java нет различени€ этих видов методов.

Ѕазовый класс Object

 ласс Object €вл€етс€ базовым дл€ всех классов Java. ѕоэтому все его пол€ и методы наследуютс€ и содержатс€ во всех классах. ¬ классе Object содержатс€ следующие методы:

public Boolean equals(Object obj) Ц возвращает true в случае, когда равны значени€ объекта, из которого вызываетс€ метод, и объекта, передаваемого через ссылку obj в списке параметров. ≈сли объекты не равны, возвращаетс€ false. ¬ классе Object равенство рассматриваетс€ как равенство ссылок и эквивалентно оператору сравнени€ У==Ф. Ќо в потомках этот метод может быть переопределЄн, и может сравнивать объекты по их содержимому. Ќапример, так происходит дл€ объектов оболочечных числовых классов. Ёто легко проверить с помощью такого кода:

Double d1=1.0,d2=1.0;

System.out.println("d1==d2 ="+(d1==d2));

System.out.println("d1.equals(d2) ="+(d1.equals(d2)));

ѕерва€ строка вывода даст d1==d2 =false, а втора€ d1.equals(d2) =true

 

public int hashCode() Ц выдаЄт хэш-код объекта. ’эш-кодом называетс€ условно уникальный числовой идентификатор, сопоставл€емый какому-либо элементу. »з соображений безопасности выдавать адрес объекта прикладной программе нельз€. ѕоэтому в Java хэш-код замен€ет адрес объекта в тех случа€х, когда дл€ каких-либо целей надо хранить таблицы адресов объектов.

protected Object clone() throws CloneNotSupportedException Ц метод занимаетс€ копированием объекта и возвращает ссылку на созданный клон (дубликат) объекта. ¬ наследниках класса Object его об€зательно надо переопределить, а также указать, что класс реализует интерфейс Clonable. ѕопытка вызова метода из объекта, не поддерживающего клонировани€, вызывает возбуждение исключительной ситуации CloneNotSupportedException (У лонирование не поддерживаетс€Ф). ѕро интерфейсы и исключительные ситуации будет рассказано в дальнейшем.

–азличают два вида клонировани€: мелкое (shallow), когда в клон один к одному копируютс€ значени€ полей оригинального объекта, и глубокое (deep), при котором дл€ полей ссылочного типа создаютс€ новые объекты, клонирующие объекты, на которые ссылаютс€ пол€ оригинала. ѕри мелком клонировании и оригинал, и клон будут ссылатьс€ на одни и те же объекты. ≈сли объект имеет пол€ только примитивных типов, различи€ между мелким и глубоким клонированием нет. –еализацией клонировани€ занимаетс€ программист, разрабатывающий класс, автоматического механизма клонировани€ нет. » именно на этапе разработки класса следует решить, какой вариант клонировани€ выбирать. ¬ подавл€ющем большинстве случаев требуетс€ глубокое клонирование.

public final Class getClass() Ц возвращает ссылку на метаобъект типа класс. — его помощью можно получать информацию о классе, к которому принадлежит объект, и вызывать его методы класса и пол€ класса.

protected void finalize() throws Throwable Ц вызываетс€ перед уничтожением объекта. ƒолжен быть переопределЄн в тех потомках Object, в которых требуетс€ совершать какие-либо вспомогательные действи€ перед уничтожением объекта (закрыть файл, вывести сообщение, отрисовать что-либо на экране, и т.п.). ѕодробнее об этом методе говоритс€ в соответствующем параграфе.

public String toString() Ц возвращает строковое представление объекта (настолько адекватно, насколько это возможно). ¬ классе Object этот метод реализует выдачу в строку полного имени объекта (с именем пакета), после которого следует символ С@Т, а затем в шестнадцатеричном виде хэш-код объекта. ¬ большинстве стандартных классов этот метод переопределЄн. ƒл€ числовых классов возвращаетс€ строковое представление числа, дл€ строковых Ц содержимое строки, дл€ символьного Ц сам символ (а не строковое представление его кода!). Ќапример, следующий фрагмент кода

Object obj=new Object();

System.out.println(" obj.toString() даЄт "+obj.toString());

Double d=new Double(1.0);

System.out.println(" d.toString()даЄт "+d.toString());

Character c='A';

System.out.println("c.toString() даЄт "+c.toString());

 

обеспечит вывод

obj.toString() даЄт java.lang.Object@fa9cf

d.toString()даЄт 1.0

c.toString()даЄт A

“акже имеютс€ методы notify(), notifyAll(), и несколько перегруженных вариантов метода wait, предназначенные дл€ работы с потоками (threads). ќ них говоритс€ в разделе, посв€щЄнном потокам.





ѕоделитьс€ с друзь€ми:


ƒата добавлени€: 2017-02-28; ћы поможем в написании ваших работ!; просмотров: 717 | Ќарушение авторских прав


ѕоиск на сайте:

Ћучшие изречени€:

—амообман может довести до саморазрушени€. © Ќеизвестно
==> читать все изречени€...

2233 - | 2080 -


© 2015-2024 lektsii.org -  онтакты - ѕоследнее добавление

√ен: 0.031 с.