2014-02-13 3 views
1

У меня есть класс Java:Убедитесь, что объекты Groovy ArrayList одного и того же класса

public class Parent 
{ 
    public int parentVal; 
} 

, который будет иметь несколько унаследованных Groovy классы, как:

class Child1 extends Parent 
{ 
    def value1; 
} 

class Child2 extends Parent 
{ 
    def value2; 
} 

Я хотел бы иметь коллекцию Groovy, который будет содержать только экземпляры Child1 или Child2, так что если коллекция содержит экземпляры Child1, она не может содержать экземпляры Child2 (или что-то еще). Это моя попытка это:

import java.util.ArrayList; 

public class MyCollection<T extends Parent> 
{ 
    private ArrayList<T> list = new ArrayList<T>(); 

    public void setType(Class<T> cls) 
    { 
     this.cls = cls; 
    } 

    public void add(T item) throws Exception 
    { 
     if(item.getClass() == cls) 
     { 
      list.add(item); 
     } 
     else 
     { 
      throw new Exception("wrong argument type"); 
     } 
    } 

    public T getItem(int index) 
    { 
     return list.get(index); 
    } 

    private Class<T> cls; 
} 

и в моей Groovy сценария:

def c1 = new Child1() 
c1.value1 = 1 
c1.parentVal = 2; 

def c2 = new Child2() 
c2.value2 = 2 
c2.parentVal = 3; 

def myCol = new MyCollection() 
myCol.setType(Child1.class) 

myCol.add(c1) 
myCol.add(c2) // throws an exception 

Последнее утверждение действительно бросает «неправильный аргумент типа» исключение, но я новичок в Java и Groovy, так что я Вероятно, все это неправильно. Любые советы высоко ценится.

ответ

3

То, как вы это сделали, - это ошибка времени выполнения. Это не так, это просто не проверено во время компиляции. Я не уверен, что вы могли бы, используя дженерики Java, определить верхнюю границу и нижнюю границу в той же декларации. Просто используя <T extends Parent>, в нем говорится, что вы готовы ко всему, что распространяется на Parent, и это включает в себя Child2, пока вы только хотели Child1. Альтернативой, которую я могу думать, является определение дженериков в родительском элементе и объявление его в классе Child с самим классом, являющимся общим параметром. Затем он выдает ошибку компилятора. Также обратите внимание на @CompileStatic или @TypeChecked необходимы:

Parent класс с декларацией генериков:

class Parent<T> { 
    int parentVal 
} 

class Child1 extends Parent<Child1> { 
    def value1; 
} 

class Child2 extends Parent<Child2> { 
    def value2; 
} 

class MyCollection<T extends Parent<T>> { 
    def list = new ArrayList<T>() 

    void add(T item) throws Exception { 
     list.add(item); 
    } 

    T getItem(int index) { 
     return list.get(index); 
    } 
} 

И тестовый скрипт. Обратите внимание на комментируемой строке не компилируется:

//and in my Groovy script: 
@groovy.transform.TypeChecked 
def main() { 
    def c1 = new Child1() 
    c1.value1 = 1 
    c1.parentVal = 2; 

    def c2 = new Child2() 
    c2.value2 = 2 
    c2.parentVal = 3; 

    def myCol = new MyCollection<Child1>() 

    myCol.add(c1) 
    //myCol.add(c2) // doesn't compile 
} 


main() 
+0

Спасибо вам обоим для ответов –

1

С заводной поддерживает генерики

http://groovy.codehaus.org/Generics

Вы могли бы сделать с объявляя ArrayList<Child1> и заводной бы решить эту проблему для вас.

+0

Оказывается, что событие, если я заявляю и ArrayList в заводной он принимает экземпляры Child2 или целые события –

+3

Попробуйте с '@ CompileStatic' или' @ TypeChecked' –

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