дженерики и вопрос наследования - PullRequest
0 голосов
/ 26 марта 2011

У меня есть три класса:

public abstract class fileHandler<Key extends Object, Value extends Object> {
}    

public A extends fileHandler<String, String[]> {
}

public B extends fileHandler<String, String> {
}

Теперь в моей основной функции я делаю что-то вроде этого:

fileHandler file= null;
If (<condition>) {
    fileHandler = new A();
} else
    fileHandler = new B():
}

Но это дает 2 ошибки времени компиляции:

  1. Невозможно преобразовать A в fileHandler
  2. Невозможно преобразовать B в fileHandler

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

Обновление:

Моя иерархия классов:

  1. class fileHandler<Key, Value> { }
  2. class A extends fileHandler<String, String[]> { }
  3. class B extends fileHandler<String, String> { }
  4. класс C, вызывающий функцию gen(object of A) или
  5. класс D, вызывающий функцию gen(object of B).
  6. C и D являются производными от абстрактного класса E.

Теперь, как мне определить эти функции в C и D и E:

Я дал следующее:

E

public abstract void gen (fileHandler A) throws exception;

C

void gen (fileHandler A) throws exception;
* * D тысяча сорок-девять:
void gen (fileHandler A) throws exception;

C, D и E дают ошибку fileHandler - тип raw. Ссылка на универсальный тип fileHandler (Key, Value) должна быть параметризована.

Ответы [ 4 ]

3 голосов
/ 26 марта 2011

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

Ваш код эквивалентен следующему:

// Java defaults unspecified type arguments to Object.
fileHandler<Object, Object> file;

if (...) {
   // Error: fileHandler<String, String> is not equivalent to fileHandler<Object, Object>
   file = new fileHandler<String, String>();
} else {
   // Error: fileHandler<String, String[]> is not equivalent to fileHandler<Object, Object>
   file = new fileHandler<String, String[]>();
}

Если вы действительно хотите изолировать полиморфный интерфейс, который не зависит от типов, используемых для создания экземпляраваш класс fileHandler, тогда я бы предложил вам использовать интерфейс:

interface IFileHandler
{
    // If this interface needs to talk about keys and values, it
    // does so using only java.lang.Object.
}

public class fileHandler<Key extends Object, Value extends Object>
    implements IFileHandler
{
    // ...
}

public class A extends fileHandler<String, String>
{
    // ...
}

public class B extends fileHandler<String, String[]>
{
    // ...
}

IFileHandler file;

if (...) {
    file = new A();
} else {
    file = new B();
}
1 голос
/ 26 марта 2011

Я не получаю ошибку компиляции ... если я исправлю всю ошибку в предоставленном вами коде

  class fileHandler<Key, Value> {
    }

  class A extends fileHandler<String, String[]> {
    }

  class B extends fileHandler<String, String> {
    }

тогда

fileHandler file= null;
if (/* condition */) 
{
    file = new A();
} 
else
{
    file = new B();
}
1 голос
/ 26 марта 2011

Проблема в том, что вы пытаетесь присвоить экземпляр имени класса.Вместо этого вы должны сказать

if (condition) {
   file = new A();    
} else {
   file = new B();
}

"file" - это ссылка, здесь "fileHandler" - это имя класса.

0 голосов
/ 26 марта 2011

Как вы решите исправить это предупреждение, зависит от того, что вы пытаетесь сделать, и насколько строго вы хотите ограничить разрешенные типы для параметра gen().

Пример 1

Очень свободно

abstract class E {
    public abstract void gen(fileHandler<?,?> A) throws Exception;
}

class C extends E {
    @Override
    public void gen(fileHandler<?,?> A) throws Exception {}
}

Пример 2

Ограничить Key универсальным значением String

abstract class E {
    public abstract void gen(fileHandler<String,?> A) throws Exception;
}

class C extends E {
    @Override
    public void gen(fileHandler<String,?> A) throws Exception {}
}

Пример 3

Возможно, вы хотите назвать неограниченный тип, чтобы вы могли ссылаться на него.

abstract class E {
    public abstract <Value> void gen(fileHandler<String,Value> A) throws Exception;
}

class C extends E {
    @Override
    public <Value> void gen(fileHandler<String,Value> A) throws Exception {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...