Ћекции.ќрг


ѕоиск:




 атегории:

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

 

 

 

 


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




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

переменной некоторого объектного типа можно присваивать выражение, имеющее тот же тип или тип класса-наследника.

јналогичное правило действует при передаче фактического параметра в подпрограмму:

¬ качестве фактического параметра вместо формального параметра некоторого объектного типа можно подставл€ть выражение, имеющее тот же тип или тип класса-наследника.

¬ качестве выражени€ может выступать переменна€ объектного типа, оператор создани€ нового объекта (слово new, за которым следует конструктор), функци€ объектного типа (в том числе приведени€ объектного типа).

ѕоэтому если мы создадим переменную базового типа, дл€ которой можно писать полиморфный код, этой переменной можно назначить ссылку на объект, имеющий тип любого из классов-потомков. ¬ том числе Ц ещЄ не написанных на момент компил€ции базового класса. ѕусть, например, мы хотим написать подпрограмму, позвол€ющую перемещать фигуры из нашей иерархии не в точку с новыми координатами, как метод moveTo, а на необходимую величину dx и dy по соответствующим ос€м. ѕри этом у нас отсутствуют исходные коды базового класса нашей иерархии (либо их запрещено мен€ть). ƒл€ этих целей создадим класс FiguresUtil (сокращение от Utilities Ц утилиты, служебные программы), а в нЄм зададим метод moveFigureBy (Упереместить фигуру наФ).

 

public class FiguresUtil{

 

public static void moveFigureBy(Figure figure,int dx, int dy){

figure.moveTo(figure.x+dx, figure.y+dy);

}

}

 

¬ качестве фактического параметра такой подпрограммы вместо figure можно подставл€ть выражение, имеющее тип любого класса из иерархии фигур. ѕусть, например, нова€ фигура создаЄтс€ по нажатию на кнопку в зависимости от того, какой выбор сделал пользователь во врем€ работы программы: если в радиогруппе отмечен пункт У“очкаФ, создаЄтс€ объект типа Dot. ≈сли в радиогруппе отмечен пункт УќкружностьФ, создаЄтс€ объект типа Circle. ≈сли же отмечен пункт У ругФ, создаЄтс€ объект типа FilledCircle. ќтметим также, что класс FilledCircle был написан уже после компил€ции классов Figure, Dot и Circle.

‘рагмент кода дл€ класса нашего приложени€ будет выгл€деть так:

 

 

Figure figure;

java.awt.Graphics g=jPanel1.getGraphics();

 

//обработчик кнопки создани€ фигуры

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

if(jRadioButton1.isSelected())

figure=new Dot(g,jPanel1.getBackground());

if(jRadioButton2.isSelected())

figure=new Circle(g,jPanel1.getBackground());

if(jRadioButton3.isSelected())

figure=new FilledCircle(g,jPanel1.getBackground(),20,

java.awt.Color.BLUE);

figure.show();

}

 

//обработчик кнопки передвижени€ фигуры

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {

int dx= Integer.parseInt(jTextField1.getText());

int dy= Integer.parseInt(jTextField2.getText());

FiguresUtil.moveFigureBy(figure,dx,dy);

}

 

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

—ледует обратить внимание на ещЄ один момент Ц стиль написани€ вызова FiguresUtil.moveFigureBy(figure,dx,dy);

 

ћожно было бы написать его так:

FiguresUtil.moveFigureBy(

figure,

Integer.parseInt(jTextField1.getText()),

Integer.parseInt(jTextField2.getText())

);

 

ѕри этом экономились бы две локальные переменные (аж целых 8 байт пам€ти!), но читаемость, понимаемость и отлаживаемость кода стали бы гораздо меньше.

 

„асто встречающа€с€ ошибка: пытаютс€ присвоить переменной типа УнаследникФ выражение типа УпрародительФ. Ќапример,

Figure figure;

Circle circle;

Е

figure =new Circle (); //так можно

Е

circle= figure; - “ак нельз€! ¬ыдастс€ ошибка компил€ции. Ќесмотр€ на то, что переменной figure назначен объект типа Circle Ц ведь проверка на допустимость присваивани€ делаетс€ на этапе компил€ции, а не динамически.

≈сли программист уверен, что объект имеет тип класса-потомка, в таких случа€х надо использовать приведение типа. ƒл€ приведени€ типа перед выражением или именем переменной в круглых скобках став€т им€ того типа, к которому надо осуществить приведение:

Figure figure;

Circle circle;

Dot dot;

Е

figure =new Circle (); //так можно

Е

circle= (Circle)figure; //так можно!

dot=(Dot) figure; //так тоже можно!

 

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

ѕриводить тип можно как в сторону генерализации, так и в сторону специализации.

ѕриведение в сторону генерализации €вл€етс€ безопасным, так как объект класса-потомка всегда €вл€етс€ экземпл€ром прародител€, хоть и усложнЄнным ј вот приведение в сторону специализации €вл€етс€ опасным Ц вполне допустимо, что во врем€ выполнени€ программы окажетс€, что объект, назначенный переменной, не €вл€етс€ экземпл€ром нужного класса. Ќапример, при приведении (Circle)figure может оказатьс€, что переменной figure назначен объект типа Dot, который не может быть приведЄн к типу Circle. ¬ этом случае возникает исключительна€ ситуаци€ приведени€ типа (typecast).

¬озможна программна€ проверка того, что объект €вл€етс€ экземпл€ром заданного класса:

if(figure instanceof Circle)

System.out.println("figure instanceof Circle");

 

»ногда вместо работы с самими классами бывает удобно использовать ссылки на класс. ќни получаютс€ с помощью доступа к полю.class из любого класса.

¬озможно создание переменных типа Уссылка на классФ:

Class c=Circle.class;

»х можно использовать дл€ обращени€ к переменным класса и методам класса.  роме того, переменных типа Уссылка на классФ можно использовать дл€ создани€ экземпл€ров этого класса с помощью метода newInstance():

Circle circle=(Circle)c.newInstance();

 

¬озможна программна€ проверка соответстви€ объекта нужному типу с помощью ссылки на класс:

if(figure.getClass()==Circle.class)

circle= (Circle)figure;

Е;

Ќо следует учитывать, что при такой проверке идЄт сравнение на точное равенство классов, а не на допустимость приведени€ типов. ј вот оператор isInstance позвол€ет провер€ть, €вл€етс€ ли объект figure экземпл€ром класса, на который ссылаетс€ c:

if(c.isInstance(figure))

System.out.println("figure isInstance of Circle");

–ефакторинг

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

 

ѕриведЄм три наиболее часто встречающихс€ примера рефакторинга.

 

Ј ¬о-первых, это переименование элементов программы Ц классов, переменных, методов.

Ј ¬о-вторых, перемещение элементов программы с одного места на другое.

Ј ¬-третьих, инкапсул€ци€ полей данных.

 

¬ сложных проектах, конечно, возникают и другие варианты рефакторинга (например, выделение части кода в отдельный метод Ц УExtract methodФ), но с упом€нутыми приходитс€ встречатьс€ посто€нно. ѕоэтому рассмотрим эти три случа€ подробнее.

ѕервый случай - переименование элементов программы.

ƒл€ того, чтобы в среде NetBeans переименовать элемент, следует щЄлкнуть по его имени правой кнопкой мыши. Ёто можно сделать в исходном коде программы, а можно и в окне Projects или Navigator. ¬ по€вившемс€ всплывающем меню следует выбрать Refactor/RenameЕ ѕосле чего ввести новое им€ и нажать кнопку УNext>Ф.

 

ѕереименование класса. Ўаг 1

 

ѕереименование класса. Ўаг 2

 

≈сли галочка УPreview All ChangesФ (Уѕредварительный просмотр всех измененийФ) не сн€та, в самом нижнем окне, Output (У¬ыводФ), по€витс€ дерево со списком мест, где будут проведены исправлени€. ¬ случае необходимости галочки можно сн€ть, и в этих местах переименование проводитьс€ не будет. ѕри нажатии на кнопку УDo RefactoringФ (Уѕровести рефакторингФ) проводитс€ операци€ переименовани€ в выбранных местах программы. ¬ отличие от обычных текстовых процессоров переименование происходит с учЄтом синтаксиса программы, так что элементы, не имеющие отношени€ к переименовываемому, но имеющие такие же имена, не затрагиваютс€. „то в выгодную сторону отличает NetBeans от многих других сред разработки, не говор€ уж об обычных текстовых редакторах.

 

ѕереименование класса. Ўаг 3

 

“ребуетс€ быть внимательными: довольно часто начинающие программисты не замечают по€влени€ в окне Output списка изменений и кнопки УDo RefactoringФ. ќсобенно если высота этого окна сделана очень малой. ≈сли в диалоге переименовани€ (шаг 2) флажок УPreview all ChangesФ сн€т, при нажатии на кнопку УNext>Ф сразу происходит рефакторинг.

—ледует также отметить, что после проведени€ рефакторинга возможен возврат к первоначальному состо€нию (УоткатФ, операци€ undo). ќбычно така€ операци€ осуществл€етс€ с помощью главного меню проекта (кнопка Undo или пункт меню Edit/Undo), но в случае рефакторинга требуетс€ правой клавишей мыши вызвать всплывающее окно и выбрать пункт Refactor/Undo. ќткат может быть на несколько шагов назад путЄм повторени€ данного действи€. ѕре необходимости отказа от отката в меню рефакторинга следует выбрать пункт Redo.





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


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


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

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

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

2233 - | 2080 -


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

√ен: 0.045 с.