
Полиморфизм и расширяемость
В объектно-ориентированном программировании применение наследования предоставляет возможность расширения и дополнения программного обеспечения, имеющего сложную структуру с большим количеством классов и методов. В задачи базового класса в этом случае входит определение интерфейса (как способа взаимодействия) для всех наследников. В следующем примере приведение к базовому типу происходит в выражении:
Stone s1 = new White();
Stone s2 = new Black();
Базовый класс Stone предоставляет общий интерфейс для своих классов-наследников. Порожденные классы перекрывают эти определения для обеспечения уникального поведения.
// пример # 7 : полиморфизм : StoneRandom.java
class Stone {
public void info() {/*пустая реализация*/}
}
class White extends Stone {
public void info() {
System.out.println("добавлен белый каменный шар");
}
}
class extends Stone { Black
public void info() {
System.out.println("добавлен черный каменный шар");
}
}
public class neRandom { Sto
public static Stone randStone() {
switch((int)(Math.random() * 2)){
case 0: return new Black();
case 1: return new White();
default: return null;
/*if((int)(Math.random() * 2)==0) return new Black();
else return new White();как альтернативный и не очень
удачный вариант. Почему? */
}
}
public static void main(String[] args) {
Stone[] s = new Stone[15];
for(int i = 0; i < s.length; i++)
/* заполнение массива камнями */
s[i] = randStone();
for(int i = 0; i < s.length; i++)
s[i].info();// вызов полиморфного метода
}
}
Главный класс StoneRandom содержит static метод randStone(), который возвращает ссылку на случайно выбранный объект подкласса класса Stone каждый раз, когда он вызывается. Приведение к базовому типу производится оператором return, который возвращает ссылку на Black или White. Метод main() содержит массив из ссылок Stone, заполненный вызовами randStone(). На этом этапе известно, что имеется некоторое множество ссылок на объекты базового типа и ничего больше (не больше, чем знает компилятор). Kогда происходит перемещение по этому массиву, метод info() вызывается для каждого случайным образом выбранного объекта.
Если понадобится в дальнейшем добавить систему, например класс Green, то это потребует только переопределения метода info() и добавления одной строки в код метода randStone(), что делает систему легко расширяемой.
Статические методы и полиморфизм
К статическим методам принципы полиморфизма неприменимы. При использовании ссылки для доступа к статическому члену компилятор при выборе метода или поля учитывает тип ссылки, а не тип объекта, ей присвоенного.
/* пример # 8 : поведение статического метода :
StaticDemo.java */
class StaticA {
public static void show(){
System.out.println(
"метод show() из StaticA");
}
}
class StaticB extends StaticA {}
class StaticC extends StaticB {
public static void show(){
System.out.println(
"метод show() из StaticC");
}
}
public class StaticDemo {
public static void main(String[] args) {
StaticA s1 = new StaticC();
StaticB s2 = new StaticC();
StaticC s3 = new StaticC();
s1.show();
s2.show();
s3.show();
}
}
В результате выполнения данного кода будет выведено:
метод show() из StaticA
метод show() из StaticA
метод show() из StaticC
При таком способе инициализации объектов s1 и s2, метод show() будет вызван из суперклассов StaticA и StaticB соответственно. Для объекта s3 будет вызван собственный метод show(), что следует из способа объявления объекта. Если же спецификатор static убрать из объявления методов, то вызовы методов будут осуществляться в соответствии с принципами полиморфизма, т.е. будет вызван метод из класса StaticC.