Есть две разные вещи: сокрытие информации и абстракция.
Сокрытие информации делает возможной абстракцию, но это нечто иное. Например, используя ваш код
public class employee {
private String name;
private int id;
public void setName(String name) {
this.name = name;
}
public String getName(){
return name;
}
}
Поле id
на самом деле скрыто. Это позволяет обрабатывать идентификаторы способом, не связанным с остальной частью программы. Ваше поле имени на самом деле тоже скрыто, так как вы не имеете прямого доступа к полю имени, но код в getName
и setName
делает это.
Как только вы скроете структуру данных от остального кода, обеспечив доступ через методы, можно создать ряд заменяемых реализаций элемента. Например, employee
— это концептуальный вид person
, поэтому вы могли бы переписать приведенное выше так:
public interface Person {
public abstract String getName();
}
public class Employee implements Person {
private String name;
private int id;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Теперь ваш код может обрабатывать Employee
как Person
. После переписывания остального кода, который явно не работает с Employee
, для работы с Person
, вы можете реализовать другие виды Person
и использовать задачи, не относящиеся к сотрудникам, которые теперь являются задачами Person
.
public Customer implements Person {
private String name;
private integer moneySpent;
public String getName() {
return name;
}
}
Таким образом, процедура поиска человека, пока она индексирует только объекты Person
, теперь может включать поиск как Employee
s, так и Customer
s. Это связано с тем, что код, работающий с объектами Person
, на самом деле имеет дело с абстракцией более высокого уровня, которую разделяют как объекты Employee
, так и объекты Customer
.
При работе с объектами на абстрактном уровне имена методов являются общими для всей абстракции; но фактически выполняемый код зависит от неупомянутого базового типа объекта. Другими словами, если вы спросите человека (который оказался сотрудником) getName()
, он ответит функцией Employee.getName()
, а Customer
ответит функцией Customer.getName()
. Поскольку код, вызывающий getName()
, работает с Person
s, он понятия не имеет, с каким типом людей он будет работать, но очевидное изменение в поведении (выбор правильного блока кода для каждого объекта) все же происходит. Это явление известно как полиморфизм, и если вы впервые столкнулись с этими понятиями, вы услышите, что слово «полиморфизм» часто используется.
Пример полиморфного поведения:
public interface Animal {
public abstract String makeSound();
}
public class Cow implements Animal {
public String makeSound() {
return "Moo Moo!";
}
}
public class Dog implements Animal {
public String makeSound() {
return "Ruff Ruff!";
}
}
public class Sheep implements Animal {
public String makeSound() {
return "Baa Baa!";
}
}
// this class demonstrates the polymorphic behavior
public class Farm {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Cow());
animals.add(new Sheep());
animals.add(new Dog());
for (Animal animal : animals) {
// this is where the polymorphisim occurs
// each animal will make a different sound
// because the makeSound method is getting
// bound to different blocks of code based
// on the exact type of animal class hiding
// under the Animal abstraction.
System.out.println(animal.makeSound());
}
}
}
ожидаемый результат:
Moo Moo!
Baa Baa!
Ruff Ruff!
хотя мы никогда явно не меняли классы и никогда явно не меняли методы. Изменялась привязка абстрактного метода к явному подклассу, что происходит только в системах, поддерживающих полиморфизм.
person
Edwin Buck
schedule
02.09.2011