1128] Хотя на этот вопрос уже был дан ответ, я хотел бы расширить существующие ответы.
Как уже упоминал Странник, фигурные скобки здесь означают тело лямбды. Kotlin поддерживает размещение обратных вызовов вне регулярных скобок .
Это:
button.setOnClickListener {clickListener()}
Равно равно:
button.setOnClickListener({clickListener()})
, что равно:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickListener();
}
});
Или (только Java 8) :
button.setOnClickListener(view -> clickListener());
TL; DR: содержимое аргументов функции определяется с помощью ()
, а лямбда-тела определяются с помощью {}
(так же, как с обычными функциями, классами, интерфейсами , так далее.).
Теперь, во-первых, обратный вызов метода onClick принимает аргумент view
. Если вы используете автономную функцию, у нее должен быть следующий аргумент:
fun clickListener(view: View) { TODO("Place your listener code here") }
Это основано на именовании - если вы реализуете OnClickListener
, просто передайте this
в качестве аргумента. У вас уже есть слушатель и функция, поэтому вам не нужно явно определять, что передать. Однако, если вы реализуете OnClickListener
, обязательно проверьте идентификатор перед выполнением действия, если у вас есть несколько представлений, использующих его в качестве прослушивателя.
Если вы используете методы, следующее зависит от того, как.
var
или val
Если ваш обратный вызов определен как:
val listener = {view: View ->
TODO()
}
Вы можете передать его как аргумент:
button.setOnClickListener(listener)
[1126 ] OnClickListeners
Если у вас есть var onClickListener: OnClickListener
, применяются те же функции, что и с функциями var
/ val
.
Если у вас есть fun clickListener
, вам придется добавить лямбду, чтобы передать его. Это, как и в случае с Java, использовать ::
. Однако вам не нужно явно объявлять область действия, как в Java. Это означает, что любой из них будет работать:
button.setOnClickListener(::clickListener);
button.setOnClickListener(this::clickListener);
// alternatively with a different target, if it's somewhere else.
Я думаю, что это - разумный подход по нескольким причинам:
Кроме того, существуют те, которые утверждали, что неконтролируемые исключения не все настолько плохо. Ваше использование напоминает мне о OperationCanceledException Eclipse, который используется для выдувания из продолжительных фоновых задач.
Это не прекрасно, но, если хорошо зарегистрировано, это кажется хорошо мне.
Существует ли причина, Вы только возвращаете значение? Такой как ПУСТОЙ УКАЗАТЕЛЬ, если Вы действительно хотите ничего не возвратить? Это было бы намного более простым, и не рискнет выдавать исключение на этапе выполнения непроверенное.
При выдаче исключения на этапе выполнения, поскольку управляющая логика является определенно плохой идеей. Причина Вы чувствуете себя грязными, состоит в том, что Вы обходите систему типов, т.е. тип возврата Ваших методов является ложью.
У Вас есть несколько опций, которые являются значительно более чистыми.
1. Функтор исключений
Хорошая техника для использования, когда Вы ограничиваетесь в исключениях, которые можно выдать, если Вы не можете бросить контролируемую исключительную ситуацию, возвращает объект, который бросит контролируемую исключительную ситуацию. java.util.concurrent. Вызываемый экземпляр этого функтора, например.
Посмотрите здесь для подробного объяснения этой техники.
Например, вместо этого:
public Something visit(Node n) {
if (n.someting())
return new Something();
else
throw new Error("Remember to catch me!");
}
Сделайте это:
public Callable<Something> visit(final Node n) {
return new Callable<Something>() {
public Something call() throws Exception {
if (n.something())
return new Something();
else
throw new Exception("Unforgettable!");
}
};
}
2. Дизъюнктное объединение (иначе любой Bifunctor)
Эта техника позволяет Вам возвратить одни из двух различных типов из того же метода. Это немного похоже Tuple<A, B>
техника, что большинство людей знакомо с для того, чтобы возвратить больше чем одно значение из метода. Однако вместо того, чтобы возвращать значения обоих типов A и B, это включает возвращение единственного значения или типа A или B.
Например, учитывая Сбой перечисления, который мог перечислить применимые коды ошибок, пример становится...
public Either<Fail, Something> visit(final Node n) {
if (n.something())
return Either.<Fail, Something>right(new Something());
else
return Either.<Fail, Something>left(Fail.DONE);
}
Совершение звонка является теперь намного более чистым, потому что Вы не должны пробовать/ловить:
Either<Fail, Something> x = node.dispatch(visitor);
for (Something s : x.rightProjection()) {
// Do something with Something
}
for (Fail f : x.leftProjection()) {
// Handle failure
}
Любой класс не очень трудно записать, но полнофункциональная реализация обеспечивается библиотекой Functional Java.
3. Монада опции
Немного как безопасный с точки зрения типов пустой указатель, это - хорошая техника для использования, когда Вы не хотите возвращать значение для некоторых исходных данных, но Вам не нужны исключения или коды ошибок. Обычно люди возвратят то, что назвало "значение сигнальной метки", но Опция является значительно более чистой.
Вы теперь имеете...
public Option<Something> visit(final Node n) {
if (n.something())
return Option.some(new Something());
else
return Option.<Something>none();
}
Вызов является хорошим и чистым:
Option<Something> s = node.dispatch(visitor));
if (s.isSome()) {
Something x = s.some();
// Do something with x.
}
else {
// Handle None.
}
И то, что это - монада, позволяет Вам цепочечные вызовы, не обрабатывая специальное предложение, которое Ни один не оценивает:
public Option<Something> visit(final Node n) {
return dispatch(getIfPart(n).orElse(dispatch(getElsePart(n)));
}
Класс Опции еще легче записать, чем Также, но снова, полнофункциональная реализация обеспечивается библиотекой Functional Java.
Я вижу следующие опции для Вас:
RuntimeException
подкласс. Проверьте на серьезные проблемы путем ловли исключения в наиболее общем вызове к dispatch
и создание отчетов, что то, если это получает это далеко.Почему Вы возвращаете значение от своего посетителя? Соответствующий метод посетителя называют классы, которые посещают. Вся сделанная работа инкапсулируется в самом классе посетителя, это ничего не должно возвращать и обрабатывать свои собственные ошибки. Единственное обязательство, требуемое класса вызова, состоит в том, чтобы назвать соответствующий visitXXX метод, ничто больше. (Это предполагает, что Вы используете перегруженные методы в качестве в Вашем примере в противоположность переопределению того же посещения () метод для каждого типа).
Посещаемый класс не должен быть изменен посетителем или иметь, чтобы иметь любое знание того, что это делает, кроме него позволяет посещению происходить. Возвращение значения или выдача исключения нарушили бы это.
Необходимо ли использовать Посетителя от XTC? Это - довольно тривиальный интерфейс, и Вы могли реализовать свое собственное, которое может бросить проверенный ReturnException, который Вы не забыли бы ловить при необходимости.
Я не пользовался библиотекой XTC, которую Вы упоминаете. Как это предоставляет дополнительную часть шаблона "посетитель" - accept(visitor)
метод на узлах? Даже если это - основанный на отражении диспетчер, должно все еще быть что-то, что обрабатывает рекурсию вниз синтаксическое дерево?
Если этот структурный итеративный код с готовностью доступен, и Вы уже не используете возвращаемое значение от Вашего visitXxx(node)
методы, мог Вы использовать простое перечислимое возвращаемое значение или даже булев флаг, говоря accept(visitor)
не рекурсивно вызывать в дочерние узлы?
Если:
accept(visitor)
явно не реализован узлами (существует некоторое продолжение отражения поля или средства доступа, или узлы просто реализуют получающий ребенка интерфейс для некоторой стандартной логики потока управления, или по любой другой причине...), и
Вы не хотите смешивать со структурной частью итерации библиотеки, или это не доступно, или это не стоит усилия...
затем как последнее прибежище я предполагаю, что исключениями могла бы быть Ваша единственная опция, все еще пользуясь ванильной библиотекой XTC.
Интересная проблема, хотя, и я могу понять, почему основанный на исключении поток управления заставляет Вас чувствовать себя грязными...