Ћекции.ќрг


ѕоиск:




 атегории:

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

 

 

 

 


ѕроблемы множественного наследовани€ классов. »нтерфейсы




ƒостаточно часто требуетс€ совмещать в объекте поведение, характерное дл€ двух или более независимых иерархий. Ќо ещЄ чаще требуетс€ писать единый полиморфный код дл€ объектов из таких иерархий в случае, когда эти объекты обладают схожим поведением.  ак мы знаем, за поведение объектов отвечают методы. Ёто значит, что в полиморфном коде требуетс€ дл€ объектов из разных классов вызывать методы, имеющие одинаковую сигнатуру, но разную реализацию. ”нарное наследование, которое мы изучали до сих пор, и при котором у класса может быть только один прародитель, не обеспечивает такой возможности. ѕри унарном наследовании нельз€ ввести переменную, котора€ бы могла ссылатьс€ на экземпл€ры из разных иерархий, так как она должна иметь тип, совместимый с базовыми классами этих иерархий.

¬ C++ дл€ решени€ данных проблем используетс€ множественное наследование. ќно означает, что у класса может быть не один непосредственный прародитель, а два или более. ¬ этом случае проблема совместимости с классами из разных иерархий решаетс€ путЄм создани€ класса, наследующего от необходимого числа классов-прародителей.

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

¬ частности, так называемое ромбовидное наследование, когда у класса A наследники B и C, а от них наследуетс€ класс D. ѕоэтому класс D получает пол€ и методы, имеющиес€ в классе A, в удвоенном количестве Ц один комплект по линии родител€ B, другой Ц по линии родител€ C.

 онечно, в C++ имеютс€ средства решать указанные проблемы. Ќапример, проблемы ромбовидного наследовани€ снимаютс€ использованием так называемых виртуальных классов, благодар€ чему при ромбовидном наследовании потомкам достаЄтс€ только один комплект членов класса A, и различени€ имЄн из разных ветвей класса с помощью имЄн классов. Ќо в результате получаетс€ заметное усложнение логики работы с классами и объектами, вызывающее логические ошибки, не отслеживаемые компил€тором. ѕоэтому в Java используетс€ множественное наследование с помощью интерфейсов, лишЄнное практически всех указанных проблем.

»нтерфейсы €вл€ютс€ важнейшими элементами €зыков программировани€, примен€емых как дл€ написани€ полиморфного кода, так и дл€ межпрограммного обмена.  онцепци€ интерфейсов Java была первоначально заимствована из €зыка Objective-C, но в дальнейшем развивалась и дополн€лась. ¬ насто€щее врем€ она, фактически, стала основой объектного программировани€ в Java, заменив концепцию множественного наследовани€, используемую в C++.

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

ќтсутствие в интерфейсах полей данных и реализованных методов снимает почти все проблемы множественного наследовани€ и обеспечивает из€щный инструмент дл€ написани€ полиморфного кода. Ќапример, то, что все коллекции обладают методами, перечисленными в разделе о коллекци€х, обеспечиваетс€ тем, что их классы €вл€ютс€ наследниками интерфейса Collection. јналогично, все классы итераторов €вл€ютс€ наследниками интерфейса Iterator, и т.д.

ƒеклараци€ интерфейса очень похожа на декларацию класса:

ћодификатор¬идимости interface »м€»нтерфейса

extends »м€»нтерфейса1, »м€»нтерфейса2,..., »м€»нтерфейсаN {

деклараци€ констант;

деклараци€ заголовков методов;

}

¬ качестве модификатора видимости может использоватьс€ либо слово public Ц обща€ видимость, либо модификатор должен отсутствовать, в этом случае обеспечиваетс€ видимость по умолчанию - пакетна€. ¬ списке прародителей, расширением которых €вл€етс€ данный интерфейс, указываютс€ прародительские интерфейсы »м€»нтерфейса1, »м€»нтерфейса2 и так далее. ≈сли список прародителей пуст, в отличие от классов, интерфейс не имеет прародител€.

ƒл€ имЄн интерфейсов в Java нет специальных правил, за исключением того, что дл€ них, как и дл€ других объектных типов, им€ прин€то начинать с заглавной буквы. ћы будем использовать дл€ имЄн интерфейсов префикс I (от слова Interface), чтобы их имена легко отличать от имЄн классов.

ќбъ€вление константы осуществл€етс€ почти так же, как в классе:

ћодификатор¬идимости “ип »м€ онстанты = значение;

¬ качестве необ€зательного модификатора видимости может использоватьс€ слово public. Ћибо модификатор должен отсутствовать - но при этом видимость также считаетс€ public, а не пакетной. ≈щЄ одним отличием от декларации в классе €вл€етс€ то, что при задании в интерфейсе все пол€ автоматически считаютс€ окончательными (модификатор final), т.е. без права изменени€, и к тому же €вл€ющимис€ переменными класса (модификатор static). —ами модификаторы static и final при этом ставить не надо.

ƒеклараци€ метода в интерфейсе осуществл€етс€ очень похоже на декларацию абстрактного метода в классе Ц указываетс€ только заголовок метода:

ћодификатор¬идимости “ип »м€ћетода(списокѕараметров)

throws список»сключений;

¬ качестве модификатора видимости, как и в предыдущем случае, может использоватьс€ либо слово public, либо модификатор должен отсутствовать. ѕри этом видимость также считаетс€ public, а не пакетной. ¬ списке исключений через зап€тую перечисл€ютс€ типы провер€емых исключений (потомки Exception), которые может возбуждать метод. „асть throws список»сключений €вл€етс€ необ€зательной. ѕри задании в интерфейсе все методы автоматически считаютс€ общедоступными (public) абстрактными (abstract) методами объектов.

ѕример задани€ интерфейса:

 

package figures_pkg;

 

public interface IScalable {

public int getSize();

public void setSize(int newSize);

}

 

 ласс можно наследовать от одного родительского класса и от произвольного количества интерфейсов. Ќо вместо слова extends используетс€ зарезервированное слово implements - реализует. √овор€т, что класс-наследник интерфейса реализует соответствующий интерфейс, так как он об€зан реализовать все его методы. Ёто гарантирует, что объекты дл€ любых классов, наследующих некий интерфейс, могут вызывать методы этого интерфейса. „то позвол€ет писать полиморфный код дл€ объектов из разных иерархий классов. ѕри реализации возможно добавление новых полей и методов, как и при обычном наследовании. ѕоэтому можно считать, что это просто один из вариантов наследовани€, обладающий некоторыми особенност€ми.

”точнение: в абстрактных классах, реализующих интерфейс, реализации методов может не быть Ц наследуетс€ деклараци€ абстрактного метода из интерфейса.

«амечание: »нтерфейс также может реализовывать (implements) другой интерфейс, если в том при задании типа использовалс€ шаблон (generics, template). Ќо эта тема выходит за пределы данного учебного пособи€.

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

 

–еализации у сущности типа интерфейс не бывает, как и дл€ абстрактных классов. “о есть экземпл€ров интерфейсов не бывает. Ќо, как и дл€ абстрактных классов, можно вводить переменные типа интерфейс. Ёти переменные могут ссылатьс€ на объекты, принадлежащие классам, реализующим соответствующий интерфейс. “о есть классам-наследникам этого интерфейса.

ѕравила совместимости таковы: переменной типа интерфейс можно присваивать ссылку на объект любого класса, реализующего этот интерфейс.

— помощью переменной типа интерфейс разрешаетс€ вызывать только методы, декларированные в данном интерфейсе, а не любые методы данного объекта. ≈сли, конечно, не использовать приведение типа.

ќсновное назначение переменных интерфейсного типа Ц вызов с их помощью методов, продекларированных в соответствующем интерфейсе. ≈сли такой переменной назначена ссылка на объект, можно гарантировать, что из этого объекта разрешено вызывать эти методы, независимо от того, какому классу принадлежит объект. —итуаци€ очень похожа с полиморфизмом на основе виртуальных и динамических методов объектов. Ќо гарантией работоспособности служит не одинаковость сигнатуры методов в одной иерархии, а одинаковость сигнатуры методов в разных иерархи€х Ц благодар€ совпадению с декларацией одного и того же интерфейса. ќб€зательно, чтобы методы были методами объектов Ц полиморфизм на основе методов класса невозможен, так как дл€ вызовов этих методов используетс€ статическое св€зывание (на этапе компил€ции).





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


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


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

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

Ќачинайте делать все, что вы можете сделать Ц и даже то, о чем можете хот€ бы мечтать. ¬ смелости гений, сила и маги€. © »оганн ¬ольфганг √ете
==> читать все изречени€...

2094 - | 1901 -


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

√ен: 0.018 с.