2015-02-06 3 views
2

Я изменяю образец класса из книги и пытаюсь преобразовать его в использование обобщений, чтобы помочь мне узнать, как это работает. Вы можете увидеть мой код ниже, где я сделал попытку. Общие A, B и C используются как String String и int.Попытка понять Generics в java

public class Student<A,B,C> implements Person { 
    A id; 
    B name; 
    C age; 

    public Student(A i, B n, C a) { 
     id = i; 
     name = n; 
     age = a; 
    } 

    protected int studyHours() {return age/2;} 
    public A getID() {return id;} 
    public B getName() {return name;} 
    public C getAge() {return age;} 
    public boolean equals(Person other) { 
     if(!(other instanceof Student)) return false; 
     Student s = (Student) other; 
     return id.equals(s.id); 
    } 
    public String toString() { 
     return "Student(ID: " + id + ", Name: " + name + ", Age: " + age + ")"; 
    } 
    public static void main(String[] var0) { 
     Student<String,String,int> studentOne = new Student("123", "Guillermo", 34); 
     Student<String,String,int> studentTwo = new Student("345", "Cheryl", 35); 
     int numberOfStudyHours; 

     numberOfStudyHours = studentOne.studyHours(); 
     System.out.println("Guillermo studies " +numberOfStudyHours+ " hours"); 

    } 
} 

Человек Интерфейс ниже

public interface Person { 
    public boolean equals(Person other);  //is this the same person? 
    public String getName(); 
    public int getAge(); 
} 

Ваше опытное руководство было бы весьма признателен. Я получаю эту ошибку:

Student.java:4: error: Student is not abstract and does not override abstract method getAge() in Person 
     public class Student<A,B,C> implements Person { 
      ^
    Student.java:18: error: getAge() in Student cannot implement getAge() in Person 
      public C getAge() {return age;} 
        ^
     return type C is not compatible with int 
     where C is a type-variable: 
     C extends Object declared in class Student 
    Student.java:17: error: getName() in Student cannot implement getName() in Person 
      public B getName() {return name;} 
        ^
     return type B is not compatible with String 
     where B is a type-variable: 
     B extends Object declared in class Student 
    Student.java:15: error: bad operand types for binary operator '/' 
      protected int studyHours() {return age/2;} 
               ^
     first type: C 
     second type: int 
     where C is a type-variable: 
     C extends Object declared in class Student 
    Student.java:28: error: unexpected type 
       Student<String,String,int> studentOne = new Student("123", "Guillermo", 34); 
            ^
     required: reference 
     found: int 
    Student.java:29: error: unexpected type 
       Student<String,String,int> studentTwo = new Student("345", "Cheryl", 35); 
            ^
     required: reference 
     found: int 
+4

В чем вопрос? – vanza

+6

Не очень хороший выбор для дженериков. Имеет ли смысл, что 'id' должен быть чем угодно, кроме String или age, чтобы быть чем угодно, кроме int? Даже если бы они это сделали, у вас возникла проблема с тем, что getName должен вернуть String для реализации Person. Поэтому имя в значительной степени ограничено как String. –

+0

Привет, Майкл, я действительно не собирался его использовать ни для чего. Я просто использую его в качестве примера, чтобы окунуться в него. –

ответ

0

Для примера, похоже, вы должны изменить свой интерфейс:

public interface Person<B,C> { 
    public boolean equals(Person other);  //is this the same person? 
    public B getName(); 
    public C getAge(); 
} 

, а затем

public class Student<A,B,C> implements Person<B,C> { 
    A id; 
    B name; 
    C age; 
    ... 
} 

But this isn't really a good use of generics. Также имейте в виду, что вы не можете использовать int или другие примитивы с дженериками. Вы должны использовать Integer или другие классы бокса.

+1

Также подумайте над сообщением об ошибке « udent.java:4: ошибка: Студент не является абстрактным и не переопределяет абстрактный метод getAge()« Это означало бы, что каждый интерфейс, реализованный в классе, должен переопределить его указанный метод в интерфейсе с той же сигнатурой метода. Boggartfly

+0

@Boggartfly Right, 'Student' не является абстрактным, но реализует интерфейс' Person', что означает, что он должен реализовывать каждый метод, определенный в 'Person'. Вам нужно будет реализовать 'public C getAge();', например, 'public C getAge() {return age; } 'в' Student'. –

+0

Точно я имею в виду !! Укрепите мой комментарий. Мне очень нужна репутация. – Boggartfly

1

Для получения более подробных примеров того, где генерики имеют смысл, просмотрите различные классы Java Collections. Например, имеет смысл сделать карту от чего-либо к чему-либо еще (String to Integer, Integer to String, Integer to Integer, Person to String). Вы хотите только один класс для реализации всех этих карт, но инстанцировании каждую карту с его типами,

Map<Person,Person> motherMap = new HashMap<>(); 

компилятор и IDE знать, какой ключ должен быть уделено методу get(), и какой тип результат будет, предотвращая множество ошибок при кодировании.

Еще одно место, где можно найти примеры, когда дженерики используются для хорошего эффекта, - это библиотеки google: см. GuavaExplained.

Для практики упражнений, вы могли бы попробовать реализовать бинарное дерево с левой и правой дочерних узлов, где узлы дерева являются все же родового типа T.

За ошибки компиляции Дженерики не могут быть использованы для примитивные типы - строчные, такие как boolean и int, хотя вместо этого вы можете использовать Boolean и Integer. Кроме того, интерфейс обычно будет также общим: HashMap<K,V> implements Map<K,V>

Смежные вопросы