ПОЧЕМУ ИНТЕРФЕЙС ??????
Все начинается с собаки. В частности, мопс .
Мопс имеет различные поведения:
public class Pug {
private String name;
public Pug(String n) { name = n; }
public String getName() { return name; }
public String bark() { return "Arf!"; }
public boolean hasCurlyTail() { return true; } }
И у вас есть лабрадор, у которого также есть набор поведений.
public class Lab {
private String name;
public Lab(String n) { name = n; }
public String getName() { return name; }
public String bark() { return "Woof!"; }
public boolean hasCurlyTail() { return false; } }
Мы можем сделать несколько мопсов и лабораторий:
Pug pug = new Pug("Spot");
Lab lab = new Lab("Fido");
И мы можем ссылаться на их поведение:
pug.bark() -> "Arf!"
lab.bark() -> "Woof!"
pug.hasCurlyTail() -> true
lab.hasCurlyTail() -> false
pug.getName() -> "Spot"
Допустим, я управляю питомником собак, и мне нужно следить за всеми собаками, которых я держу. Мне нужно хранить своих мопсов и лабрадоров в отдельных массивах :
public class Kennel {
Pug[] pugs = new Pug[10];
Lab[] labs = new Lab[10];
public void addPug(Pug p) { ... }
public void addLab(Lab l) { ... }
public void printDogs() { // Display names of all the dogs } }
Но это явно не оптимально. Если я тоже хочу разместить несколько пуделей , я должен изменить свое определение питомника, чтобы добавить массив пуделей. На самом деле мне нужен отдельный массив для каждого вида собак.
Понимание: и мопсы, и лабрадоры (и пудели) являются типами собак и имеют одинаковый набор поведений. То есть мы можем сказать (для целей этого примера), что все собаки могут лаять, иметь имя и могут иметь или не иметь курчавый хвост. Мы можем использовать интерфейс для определения того, что могут делать все собаки, но оставим это на усмотрение конкретных типов собак для реализации этих специфических поведений. Интерфейс говорит: «Вот то, что могут делать все собаки», но не говорит, как выполняется каждое поведение.
public interface Dog
{
public String bark();
public String getName();
public boolean hasCurlyTail(); }
Затем я немного изменил классы Pug и Lab, чтобы реализовать поведение Dog. Можно сказать, что мопс - это собака, а лаборатория - это собака.
public class Pug implements Dog {
// the rest is the same as before }
public class Lab implements Dog {
// the rest is the same as before
}
Я все еще могу создавать экземпляры Pugs и Labs, как раньше, но теперь у меня также есть новый способ сделать это:
Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");
Это говорит о том, что d1 - это не только собака, это мопс. И d2 тоже собака, а точнее лаборатория.
Мы можем вызвать поведение, и оно работает как прежде:
d1.bark() -> "Arf!"
d2.bark() -> "Woof!"
d1.hasCurlyTail() -> true
d2.hasCurlyTail() -> false
d1.getName() -> "Spot"
Вот где вся дополнительная работа окупается. Класс питомника стал намного проще. Мне нужен только один массив и один метод addDog. Оба будут работать с любым объектом, который является собакой; то есть объекты, которые реализуют интерфейс Dog.
public class Kennel {
Dog[] dogs = new Dog[20];
public void addDog(Dog d) { ... }
public void printDogs() {
// Display names of all the dogs } }
Вот как это использовать:
Kennel k = new Kennel();
Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");
k.addDog(d1);
k.addDog(d2);
k.printDogs();
Последнее выражение будет отображаться:
Спот Фидо
Интерфейс дает вам возможность указать набор поведений, которые будут совместно использоваться всеми классами, которые реализуют интерфейс. Следовательно, мы можем определять переменные и коллекции (например, массивы), которым не нужно заранее знать, какой тип конкретного объекта они будут содержать, только что они будут содержать объекты, реализующие интерфейс.