Почему Java не позволяет пропускать формальные имена параметров в объявлении функции? - PullRequest
1 голос
/ 14 марта 2011

Я хочу понять, , почему Разработчики Java решили реализовать объявления функций таким образом.Я часто слышал, как говорят, что разработчики Java хотели избежать неудачного выбора дизайна, сделанного на других языках (например, C ++) - множественное наследование через классы и перегрузка операторов приходят кразум - чтобы сохранить объектно-ориентированную модель как можно более простой и поощрять хорошие методы программирования.Это правда в этом случае?Является ли эта функция слишком дорогой для реализации по сравнению с (по общему признанию, предельной) выгодой, которую она обеспечивает?

Дело в том, что я не вижу (и я все еще учусь,так что это, вероятно, означает приседание!: D) значительные накладные расходы на реализацию пропуска формальных имен параметров в объявлениях функций.И я могу вспомнить, по крайней мере, один пример, где эта функция не может повредить: определение абстрактных функций.

В любом случае, рад услышать некоторые мысли от людей на SO.Кстати, соответствующий раздел (8.4.1) Спецификации языка Java объясняет что , но не говорит о почему .

РЕДАКТИРОВАТЬ: Добавление фрагмента кода:

abstract void someFunc(int, int, int);

(я использую абстрактную функцию, так как это один простой случай, я могу подумать, где эта функция будет полезна).

Ответы [ 6 ]

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

Почему должно это разрешить?

Если бы определение метода не имело имен для его параметров, как бы вы фактически использовали параметры в своем коде?

В C ситуация немного отличается: у вас есть декларация и реализация независимо друг от друга (по крайней мере, если вы делаете это «правильно»). Здесь, оставляя информацию в одном месте, можно избежать дублирования.

Но в Java нет отдельного объявления (если вы не определяете метод в интерфейсе, в этом случае нет реализации, что означает повторное дублирование). Есть только реализация.

1 голос
/ 14 марта 2011

Вы можете отбросить формальные аргументы, используя перегрузку, например,

class Three {
  public Three() {
    this(1);
  }

  public Three(int a) {
    this(a, 2);
  }

  public Three(int a, int b) {
    this(a, b, 3);
  }

  public Three(int a, int b, int c) {  }

  // can pass any number of `int` values.
  public void method1(int... varargs) {
  }

  public void method2(int a) {
     method2(a, 2);
  }

  public void method2(int a, int b) { }
}

РЕДАКТИРОВАТЬ: Из моего комментария.

Проект Java имеет тенденцию ждать веской причины, чтобы что-то сделать (а затем подумать об этом еще несколько лет;) почему бы не аргумент не достаточен для включения чего-либо. Как правило, есть и другие способы сделать то же самое (если не как элемент), например использовать вместо этого перегрузку, что делает случай менее убедительным

0 голосов
/ 19 декабря 2017

Это была бы отличная возможность, потому что вы могли бы избавиться от этой глупой аннотации, чтобы игнорировать неиспользованные.

Допустим, у меня было это:

@FunctionalInterface
interface ListFunc {
    Stream<Path> apply( Path dir ) throws IOException;
}
void doStuff( Path dir, ListFunc listFunc ) {
    List<Path> filenames = listFunc.apply( dir ).collect( Collectors.toList() );
    ...

Итак, простой случай:

doStuff( Paths.get( System.getProperty( "user.home" ) ), Files::list );

А как насчет юнит-тестов?

static Stream<Path> fixedListFunc( Path /* unused */ dir ) {
    List<Path> fixed = Lists.newArrayList( Paths.get( "first" ),
            Paths.get( "second" ),
            Paths.get( "third" ) );
    return fixed.stream();
}

@Test
public void testDoStuff() {
    doStuff( null, fixedListFunc );

Конечно, было бы неплохо опустить имя для неиспользуемого параметра.Вместо того, чтобы перегружать или использовать аннотации, чтобы игнорировать предупреждение в этом случае или другие вещи.

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

Если вы говорите о именах , а не о самих аргументах, причина проста.При определении абстрактных методов вы определяете интерфейс.Чтобы интерфейс был пригоден для использования, лицо, обращающееся к нему, должно знать значение аргументов.Вот для чего нужны имена.

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

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

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

Я думаю, что это просто часть той же философии, которая делает вещи строго типизированными, например. Предполагается, что вы знаете, что такое метод и как вы его используете во время компиляции.

Речь идет о наличии интерфейса, который всегда принимает ожидаемые параметры, возвращает ожидаемые результаты и выдает ожидаемые исключения. Если у нас есть

class Adder {
    int add(int a, int b) {return a+b;}
    int add(int a, int b, int c) {return a+b+c;}
    int add(int a, int b, int c, int d) {return a+b+c+d;}
}

Тогда разработчики Java думают: если вы хотите «Adder.add» два конкретных числа, есть способ для этого. Вы никогда не вызовете этот метод с тремя или четырьмя параметрами, потому что это просто не имеет смысла для того, для чего предназначен этот метод. Если вы хотите сделать три или четыре числа из «Adder.add», вы должны сделать эти методы отдельно.

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

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

Различные ответы показывают, что не совсем понятно, о чем вы спрашиваете - приведение примера в вопросе помогло бы.

Я предполагаю, что вы захотите написать

public void method(int a, int, int) {
}

вместо

public void method(int a, int b, int c) {
}

всякий раз, когда b и c не используются нигде в методе (или метод является абстрактным или аналогичным).

Итак, почему бы и нетпозвольте опустить их:

  • Это усложнит грамматику (хотя и немного)
  • Часто вы хотите задокументировать аргументы, и для этого вам потребуются имена для них.(Это относится и к интерфейсам и абстрактным / нативным методам.)
  • Если аргументы не используются, зачем их вообще использовать?
  • С теоретической точки зрения: объявления формальных параметров являются своего родаобъявление переменной, и вы не можете иметь переменную без имени (кроме элементов массива).
  • Это может запутать читателей кода.

Когда у меня есть аргументы, которыене используется, я иногда даю им имена, такие как ignored или dummy.

...