logo
Методичка Java

Пример на использование интерфейсов

Приведём пример абстрактного класса, являющегося наследником Figure, и реализующего указанный выше интерфейс IScalable:

package figures_pkg;

public abstract class ScalableFigure extends Figure implements IScalable {

private int size;

public int getSize() {

return size;

}

public void setSize(int size) {

this.size=size;

}

}

В качестве наследника приведём код класса Circle:

package figures_pkg;

import java.awt.*;

public class Circle extends ScalableFigure {

public Circle(Graphics g,Color bgColor, int r){

setGraphics(g);

setBgColor(bgColor);

setSize(r);

}

public Circle(Graphics g,Color bgColor){

setGraphics(g);

setBgColor(bgColor);

setSize( (int)Math.round(Math.random()*40) );

}

public void show(){

Color oldC=getGraphics().getColor();

getGraphics().setColor(Color.BLACK);

getGraphics().drawOval(getX(),getY(),getSize(),getSize());

getGraphics().setColor(oldC);

}

public void hide(){

Color oldC=getGraphics().getColor();

getGraphics().setColor(getBgColor());

getGraphics().drawOval(getX(),getY(),getSize(),getSize());

getGraphics().setColor(oldC);

}

};

Приведём пример наследования интерфейсом от интерфейса:

package figures_pkg;

public interface IStretchable extends IScalable{

double getAspectRatio();

void setAspectRatio(double aspectRatio);

int getWidth();

void setWidth(int width);

int getHeight();

void setHeight(int height);

}

Интерфейс IScalable описывает методы объекта, способного менять свой размер (size). При этом отношение ширины к высоте (AspectRatio – отношение сторон) у фигуры не меняется. Интерфейс IStretchable описывает методы объекта, способного менять не только свой размер, но и “растягиваться” – изменять отношение ширины к высоте (AspectRatio).

К интерфейсам применимы как оператор instanceof, так и приведение типов. Например, фрагмент кода для изменения случайным образом размера объекта с помощью интерфейса IScalable может выглядеть так:

Object object;

...

object= Circle(...);//конструктор создаёт окружность

...

if(object instanceof IScalable){

((IScalable) object).setSize( (int)(Math.random()*80) );

}

Всё очень похоже на использование класса ScalableFigure:

Figure figure;

...

figure = Circle(...);//конструктор создаёт окружность

...

if( figure instanceof IScalable){

figure.hide();

((IScalable)figure).setSize((int)(Math.random()*80));

figure.show();

}

Но если во втором случае переменная figure имеет тип Figure, то есть связанный с ней объект обязан быть фигурой, то на переменную object такое ограничение не распространяется. Зато фигуру можно скрывать и показывать, а для переменной типа Object это можно делать только после проверки, что object является экземпляром (то есть instanceof) класса Figure.

Аналогичный код можно написать в случае использования переменной типа IScalable:

IScalable scalableObj;

...

scalableObj = Circle(...);//конструктор создаёт окружность

...

scalableObj.setSize((int)(Math.random()*80));

Заметим, что присваивание Object object= Circle(...)разрешено, так как Circle – наследник Object. Аналогично, присваивание Figure figure = Circle(...) разрешено, так как Circle – наследник Figure. И, наконец, присваивание scalableObj =Circle(...) разрешено, так как Circle – наследник IScalable.

При замене в коде Circle(...) на Dot(...) мы бы получили правильный код в первых двух случаях, а вот присваивание scalableObj = Dot (...);вызвало бы ошибку компиляции, так как класс Dot не реализует интерфейс IScalable, то есть не является его потомком.