Ковариантного типы возвращение

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

Давайте начнем со следующего класса, ConfusedClass. Класс пытается объявить два метода с той же подписью. Один из методов возвращает JTextField, а другая возвращается JPasswordField.


   import javax.swing.JTextField;

   import javax.swing.JPasswordField;



   public class ConfusedClass {



     public JTextField getTextField(){

       return new JTextField();

     }

  

     public JPasswordField getTextField(){

       return new JPasswordField();

     }

   }

Если попытаться обобщить ConfusedClass, вы получите следующую ошибку компиляции:

ConfusedClass.java:10: getTextField() is already defined in
ConfusedClass
public JPasswordField getTextField(){
^
1 error

Глядя на эту ситуацию с точки зрения класса призыв getTextField (), вы можете увидеть причину ошибки компиляции. Как бы вы указать, какой из двух методов, вы ориентируетесь? Возьмем, к примеру, этот фрагмент:


   ConfusedClass cc = new ConfusedClass();

   JTextField field = cc.getTextField();

Поскольку JPasswordField распространяется JTextField, либо вариант метода может правильно назвать.

Далее, создайте два класса, каждый из которых с различными версиями getTextField () методы. Эти два метода различаются по осуществлению и тип возвращаемого значения. Начните с следующие основания:


   import javax.swing.JTextField;



   public class ConfusedSuperClass {



     public JTextField getTextField(){

       System.out.println("Called in " this.getClass());

       return new JTextField();

     }

  

   }

Обобщение ConfusedSuperClass. Вы увидите, что он компилирует без ошибок. Теперь создайте производный класс, который распространяется ConfusedSuperClass. Производный класс попытки вернуть экземпляр JPasswordField вместо JTextField возвращается getTextField () в ConfusedSuperClass.


   import javax.swing.JPasswordField;



   public class ConfusedSubClass extends ConfusedSuperClass {



     public JPasswordField getTextField(){

       System.out.println("Called in " this.getClass());

       return new JPasswordField();

     }

  

   }

Если вы используете версию JDK до J2SE 5.0, ConfusedSubClass не будет компилироваться. Вы увидите сообщение об ошибке, подобное следующему.

ConfusedSubClass.java:5: getTextField() in ConfusedSubClass
cannot override getTextField() in ConfusedSuperClass;
attempting to use incompatible return type
found   : javax.swing.JPasswordField
required: javax.swing.JTextField
public JPasswordField getTextField(){
^
1 error

Ошибка сообщили, что вы пытаетесь использовать несовместимые тип возвращения. В самом деле, JPasswordField вы пытаетесь вернуть является подтипом JTextField. Этот же код компилируется, правильно под J2SE 5.0. Теперь разрешается отменять тип возвращаемого методом с подтипом первоначального типа. В текущем примере getTextField () в ConfusedSuperClass возвращает экземпляр типа JTextField. GetTextField () в ConfusedSubClass возвращает экземпляр типа JPasswordField.

Вы можете воспользоваться этими двумя классами с NotConfusedClient следующий класс. Этот класс создает экземпляр типа ConfusedSuperClass и типа ConfusedSubClass. Затем она вызывает getTextField () на каждом экземпляре, и отображает соответствующий тип объекта, возвращенного методом.


   import javax.swing.JTextField;



   public class NotConfusedClient {

     static JTextField jTextField;



     public static void main(String[] args) {

       System.out.println("===== Super Class =====");

       jTextField = new ConfusedSuperClass().getTextField();

       System.out.println("Got back an instance of "

         + jTextField.getClass());

       System.out.println("===== Sub Class =====");

       jTextField = new ConfusedSubClass().getTextField();

       System.out.println("Got back an instance of  "

         + jTextField.getClass());

     }

   }

Обобщение и запустить NotConfusedClient. Когда вы запустите ее, вы должны увидеть следующий вывод:

===== Super Class =====
Called in class ConfusedSuperClass
Got back an instance of class javax.swing.JTextField
===== Sub Class =====
Called in class ConfusedSubClass
Got back an instance of  class javax.swing.JPasswordField

В самом деле, вы получите тот же результат, если вы меняете тип возврата getTextField (), чтобы JTextField в ConfusedSubClass. Выигрыш происходит при использовании объектов, которые возвращаются при обращении к getTextField (). Перед J2SE 5.0, Вам необходимо опустив воспользоваться методами, которые присутствуют в производный класс, но не в базовом классе. Как вы видели, в J2SE 5.0 ConfusedSubClass компилирует с различным типом возврата, указанного для getTextField (), чем в настоящее суперкласса. Теперь вы можете использовать ваш тип ковариантной вернуться к вызвать метод, который доступен только в подтипа. Во-первых, изменили супертип следующим образом:


   public class SuperClass {



     public SuperClass getAnObject(){

       return this;

     }



   }

Добавить эксклюзивный метод соответствующего подкласса, а также изменить тип возвращаемого getAnObject () метод:


   public class SubClass extends SuperClass {



     public SubClass getAnObject(){

       return this;

     }



     public void exclusiveMethod(){

       System.out.println("Exclusive in Subclass.");

     }

  

     public static void main(String[] args) {

         System.out.println("===== Call Exclusive method =====");

         new SubClass().getAnObject().exclusiveMethod();

     



   }

Обобщение суперкласс и подкласс, затем запустите SubClass. Вы должны увидеть следующее сообщение:

===== Call Exclusive method =====
Exclusive in Subclass.

Основной () метод создает экземпляр подкласса. Затем она вызывает getAnObject (). Из этого следует, это с призывом exclusiveMethod () на возвращен объект типа SubClass. Если тип возврата getAnObject () была SuperClass в SubClass.java, код не будет скомпилирован.

Copyright (C) 2004-2005 Sun Microsystems, Inc
Все права защищены.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>