Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4 конспект лекций ООП Java.doc
Скачиваний:
28
Добавлен:
03.05.2015
Размер:
962.05 Кб
Скачать

Абстрактные классы и интерфейсы

Абстрактные классы объявляются с ключевым словом abstract и  содержат объявления абстрактных методов, которые не реализованы в этих классах, а будут реализованы в подклассах. Объекты таких классов создать нельзя, но можно создать объекты подклассов, которые реализуют эти методы. Абстрактные классы могут содержать и полностью реализованные методы.

Интерфейсы представляют полностью абстрактные классы: ни один из объявленных методов не может быть  реализован. Все объявленные методы автоматически трактуются как publicиabstract, а все атрибуты – какpublic, staticиfinal. Каждый интерфейс может быть реализован одним или несколькими классами. Класс может реализовывать любое число интерфейсов, указываемых после ключевого словаimplements, дополняющего определение класса. На множестве интерфейсов также определена иерархия по наследованию, но она не имеет отношения к иерархии классов. В языке Java интерфейсы обеспечивают большую часть той функциональности, которая в C++ представляется с помощью механизма множественного наследования. Определение интерфейса имеет вид:

[public] interface имя [extends I1,I2,…,IN]{/*реализация*/}

Реализация интерфейсов классом может иметь вид:

[доступ] class имя_класса implements I1,I2, …,IN {/*реализация класса*/}

Здесь I1,I2, …,IN перечень используемых интерфейсов. Класс, который реализует интерфейс, должен предоставить полную реализацию всех методов, объявленных в интерфейсе. Кроме этого, данный класс может объявлять свои собственные методы. Если класс расширяет интерфейс, но полностью не реализует его методы, то этот класс должен быть объявлен какabstract.

/* пример # 2 : интерфейс и его реализации : InterfacesDemo.java */

interfaceAuto{

 String getMark();//объявление методов

 String getPassangers();

 String getWheels();

   }

class Bus implements Auto{//реализация интерфейса

   public String getMark(){return "Mercedes";}

   public String getPassangers(){return "90 человек";}

   public String getWheels(){return "6 колес";}

}

class Car implements Auto{

   public String getMark(){return "BMW";}

   public String getPassangers(){return "5 человек";}

   public String getWheels(){return "4 колеса";}

}

//метод getWheels() в следующем абстрактном классе не реализован

abstract class Truck implements Auto{

   public String getMark(){return "Renault";}

   public String getWheels(){return "24 колеса";}

}

public  class InterfacesDemo {

 public static void main(String[] args){

  Car c = new Car();

  Bus b = new Bus();

       printFeatures(c);

       printFeatures(b);

}

public static void printFeatures(Auto f){

 System.out.println("марка:" + f.getMark() + " вместимость:" +

 f.getPassangers() + " количество колес: " + f.getWheels());

  }

}

Класс InterfacesDemoсодержит методprintFeatures(), который вызывает методы того объекта, который передается ему в качестве параметра. Вначале ему передается объект, соответствующий легковому автомобилю, затем автобусу (объектысиb). Каким образом методprintFeatures()может обрабатывать объекты двух различных классов? Все дело в типе передаваемого этому методу аргумента – класса, реализующего интерфейсAuto.Вызывать, однако, можно только те методы, которые были объявлены в интерфейсе.

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

// пример # 3 : динамический вызов методов : TestCall.java

interfaceCall{

int NUMBER = 10; // final по умолчанию

}

interface Callback extends Call{

void callB(); /* abstract по умолчанию */

//inti; // ошибка, если нет инициализации

//voidmethod(){/*код*/} // ошибка, т.к. абстрактный метод не //может иметь тела!

}

class Client implements Callback {

   public void callB() {

  System.out.println("метод callB() вызван со значением = " + NUMBER);

}

}

class XClient implements Callback {

   public void callB() {

     System.out.print("другая версия метода callВ():");

     System.out.println("NUMBER в квадрате = " + (NUMBER*NUMBER));

   }

}

public class TestCall{

     public static void main(String[] args) {

       Callbackc=newClient();//ссылка на интерфейсный тип

  Client cl = new Client();

       XClient ob = new XClient();

   c.callB();

   c = ob; // присваивается ссылка на другой объект

   c.callB();

   //cl=ob;//ошибка! разные ветви наследования

   }

}

Результат:

метод сallB() вызван со значением = 10

другая версия метода callB(): NUMBER в квадрате = 100

Кроме того, что нельзя присваивать значения ссылок, находящихся в разных цепочках наследования, по этой же причине ошибку вызовет  операция типа Client cl = new XClient();

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]