Создать объект универсального класса - PullRequest
1 голос
/ 29 марта 2012

(с использованием Java) Я реализую универсальный класс, который является B-Tree. Когда пользователь запускает программу, он может предоставить некоторые аргументы, которые будут определять тип дерева (Integer, Character, Double или String).

В моем основном методе у меня есть этот код:

// Get user input and split it into tokens
// Tokens[1] = the type specified by the user

if( tokens[1].equals("DOUBLE"))
    BTree<Double> t = new BTree<Double>();

else if( tokens[1].equals("CHARACTER"))
    BTree<Character> t = new BTree<Character>();

else if( tokens[1].equals("INTEGER"))
    BTree<Integer> t = new BTree<Integer>();

else if( tokens[1].equals("STRING"))
    BTree<String> t = new BTree<String>();

Но компилятор жалуется, если у меня есть операторы if. Если я удаляю их, он компилируется и работает нормально: / Как я могу это исправить? Чтобы пользователь мог указать тип, и дерево будет создано в зависимости от предоставленного типа? Спасибо.

Вот некоторые из выводов компилятора:

C:\Users\User\Desktop>javac *.java
Main.java:42: error: cannot find symbol
BTree<Double> t = new BTree<Double>();
symbol:   variable BTree
location: class Main

Main.java:42: error: cannot find symbol
BTree<Double> t = new BTree<Double>();
symbol:   variable Double
location: class Main

Main.java:42: error: cannot find symbol
BTree<Double> t = new BTree<Double>();
symbol:   variable t
location: class Main

.. Есть еще, но это похоже и повторяется для каждого из типов

Ответы [ 5 ]

1 голос
/ 29 марта 2012

Переменная t в каждом из операторов if определяется только в контексте if, вне их компилятор их не распознает.
Определите вашу переменную t перед if заявлений.

BTree<?> t = null;
if( tokens[1].equals("DOUBLE")) {
    t = new BTree<Double>();
}
else if( tokens[1].equals("CHARACTER")) {
    t = new BTree<Character>();
}
else if( tokens[1].equals("INTEGER")) {
    t = new BTree<Integer>();
}
else if( tokens[1].equals("STRING")) {
    t = new BTree<String>();
}
// now you can use your 't'
1 голос
/ 29 марта 2012

Ваш класс BTree<T> не должен быть абстрактным, так как вы, похоже, хотите создать одну и ту же функциональность для всех типов типа T.

Если вам нужны специальные функции для различных типов T, вам нужно либо реализовать

class CharacterBTree extends BTree<Character>

, либо сделать это на лету, как

 BTree<Character> t = new BTree<Character>() {
    ...
 };

Также;объявите вашу BTree<T> t переменную вне if, чтобы ваш код стал

BTree<?> t = null;
if ("char".equals(whatever)) {
   t = new BTree<Character>();
} else if {
  ...
}
0 голосов
/ 29 марта 2012

Если вы пытаетесь что-то вроде

if (tokens[1].equals("DOUBLE"))
  BTree<Double> t = new BTree<Double>();
else if (tokens[1].equals("CHARACTER"))
  BTree<Character> t = new BTree<Character>();
// etc.

t.doStuff();

Это не сработает. Во-первых, потому что переменные t находятся только в области действия их операторов if, а во-вторых, потому что вы не можете сделать так, чтобы переменные имели разные статические типы по разным путям кода.

Вы могли бы сделать что-то вроде

BTree<?> t;
if (tokens[1].equals("DOUBLE"))
  t = new BTree<Double>();
else if (tokens[1].equals("CHARACTER"))
  t = new BTree<Character>();
// etc.

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

Вы можете создать интерфейс - давайте назовем его ValueHolder - и использовать его для определения любых операций, которые вам нужно выполнить над значениями в дереве. Затем определите классы, такие как DoubleHolder, CharacterHolder и т. Д., Которые реализуют интерфейс ValueHolder. Тогда вы можете написать:

BTree<? extends ValueHolder> t;
if (tokens[1].equals("DOUBLE"))
  t = new BTree<DoubleHolder>();
else if (tokens[1].equals("CHARACTER"))
  t = new BTree<CharacterHolder>();
// etc.

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

0 голосов
/ 29 марта 2012

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

switch(tokens[1]) {
    case "DOUBLE" : BTree<Double> t = new BTree<Double>(); break;
    ....
    ....
}
0 голосов
/ 29 марта 2012

Вставьте фигурные скобки:

if( tokens[1].equals("DOUBLE")){
    BTree<Double> t = new BTree<Double>();
}
else if( tokens[1].equals("CHARACTER")){
    BTree<Character> t = new BTree<Character>();
}
else if( tokens[1].equals("INTEGER")){
    BTree<Integer> t = new BTree<Integer>();
}
else if( tokens[1].equals("STRING")){
    BTree<String> t = new BTree<String>();
}

Или объявите свое дерево перед заявлением:

BTree<? extends Object> t = null;
if( tokens[1].equals("DOUBLE"))
    t = new BTree<Double>();
else if( tokens[1].equals("CHARACTER"))
    t = new BTree<Character>();
else if( tokens[1].equals("INTEGER"))
    t = new BTree<Integer>();
else if( tokens[1].equals("STRING"))
    t = new BTree<String>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...