В Java, как я могу вернуть String или double в зависимости от обстоятельств метода? Является ли это возможным? - PullRequest
3 голосов
/ 16 октября 2010

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

Если пользователь вызывает мой методчтобы вернуть элемент X из выделенного списка, я хочу, чтобы он возвращал строку, если элемент X является именем, или двойной, если элемент X является числом.

Например, objectName.get(5); получит 5-йпункт в исключенном списке.

Должен ли я использовать для этого какой-то тип перегрузки?

Или мне придется вместо этого сделать что-то вроде objectName.getDouble(5); и objectName.getString(5);, основываясь на фактечто пользователь знает, что такое элемент 5?

Но что, если пользователь не знает, что такое элемент 5?Он просто нуждается в String или Double в зависимости от того, что случилось.

Ответы [ 4 ]

7 голосов
/ 16 октября 2010

Вот один из способов сделать это:

public Object get() {
    if (blueMoon) {
        return new Double(42.0);
    } else {
        return "fred";
    }
}

Обратите внимание, что это вернет оболочку Double, а не double.

Я не думаю, что этохорошая идея, тем не менее, так как вызывающая сторона теперь должна проверить тип возвращаемого значения и выполнить Typecast, чтобы сделать что-то с ним.

Для записи Java не позволяет методу возвращать String илиdouble потому что эти типы не имеют общего супертипа в системе типов Java.

6 голосов
/ 16 октября 2010

Для такого рода вещей я предпочитаю использовать что-то похожее на шаблон Maybe / Option из лагеря функционального программирования.В результате вы получаете интерфейс, подобный следующему:

public abstract class DoubleOrString 
{
    // Constraint isDouble() xor isString()
    public boolean isDouble();
    public boolean isString();

    //Must throw iff !isString()
    public String getString();

    //Must throw iff !ifDouble()
    public Double getDouble();

    public static DoubleOrString wrap(final double wrapMe)
    {
       return new DoubleOrString()
       {
             public boolean isDouble() {return true;}
             public boolean isString() {return false;}
             public Double getDouble() {return wrapMe;}
             public String getString() {throw new RuntimeException();}
       };
    }

    //same for wrap(String)
}

. Это вызывает проблему у клиентов, поскольку всегда существует проверка работоспособности, что в соответствующее время действительно имел место тип double или String.В вашем случае я бы сделал только один метод get (), поэтому, когда клиент (думает, что он) знает, что это за тип, вызывается

objectName.get(5).getString();

и в вашем методе get (int),вместо того, чтобы возвращать String или double, оператор return выглядит так:

DoubleOrString.wrap(theThingToReturn)

Это немного дополнительная работа, но в прошлом она меня несколько раз оплачивала.

Вот как вы можете использовать его для его создания (предупреждение - это не было рядом с компилятором)

public static DoubleOrString parseADoubleOrString(String input) {
    try {
        return DoubleOrString.wrap(Integer.parseInt(input))
    } catch (NumberFormatException nfe) {
        return DoubleOrString.wrap(input);
    }
}

, а вот как выглядит клиент

  String input = //get the input from the user somehow
  DoubleOrString parsed = parseADoubleOrString(input);
  if (parsed.isDouble())
      aFunctionThatTakesADouble(parsed.getDouble());
  else
      aFunctionThatTakesAString(parsed.getString());
2 голосов
/ 16 октября 2010

Если вам нужно сделать это, значит, есть проблема с вашим дизайном.Поскольку исходным источником данных является String, вы должны принять, что все возвращаемые значения будут строковыми, и предоставить его клиенту для проверки возможности преобразования результата в число.чек, вы можете предоставить ему минимальный API, который может выглядеть примерно так:

public class ValueExtractor {

    public ValueExtractor(String delimitedText) {
        // ...
    }

    /**
     * Determines whether there is a next element
     * to be returned
     */
    public boolean next() {
        // ...
    }

    public String get() {
        // ...
    }

    /**
     * Returns the value as a Double if possible
     * null otherwise.
     */
    public Double getPossibleDouble() {
        // ...
    }
}
0 голосов
/ 16 октября 2010

Язык Java не предоставляет перегрузки для возвращаемого типа метода. (Как отметил Тило, это ограничение языка Java, а не JVM / байт-код.)

Как правило, такие вещи плохо вписываются в систему типов Java.Можно представить возвращение типа Either<String,Double> (более ограниченный тип возврата, чем Object, как предложено Стивеном С., и более общий тип, чем DoubleOrString, как указано Б. Медведем), но общие усилия, необходимые для использования такой конструкциив Java, как правило, приводит к простому использованию нескольких методов, например, getString(...) и getDouble(...).

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