Могу я написать:
@IdRes
abstract fun getHeaderId(): Int
С val вместо fun в котлине? Он жалуется, что мне нужно поле поддержки или делегат, когда я пишу:
@IdRes <-- errors
abstract val headerId: Int
Что в данном случае наиболее идиоматично? Однострочный с fun или возиться с резервным полем (я не привык к резервным полям, возможно, это устойчивость к изменениям, я никогда не использовал их, поэтому я думаю, что они неприятны)
Поскольку абстрактный val или var - это просто функция без поля поддержки, она не может быть аннотирована аннотацией IdRes, но есть обходной путь. Вы можете использовать это так:
@get:IdRes
abstract val headerId: Int
Обновлено:
Почему это работает? Нам нужно внимательнее изучить аннотацию IdRes и ее исходный код:
@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE})
public @interface IdRes {
}
Как мы видим, эту аннотацию можно использовать для методов, параметров, полей и локальных переменных. Когда мы используем abstract val, он не является ни тем, ни другим, поскольку он абстрактный, и у нас не может быть абстрактных полей в Java. Обычно эквивалент abstract val something: Int в Java:
private int something
public int getSomething() {
return something;
}
Из примера легко увидеть, что частное поле - это то, что называется резервным полем свойства, и вы не можете иметь их как абстрактные, поэтому в этом и заключалась проблема.
Я только что наткнулся на этот пост с той же проблемой (за исключением того, что мой val находится в интерфейсе) и пришел к тому же решению, но на самом деле оно не работает. в классах, которые реализуют мой интерфейс и переопределяют этот val, аннотация не принимается во внимание, и я могу передать любой int
Как упоминалось в комментарии @AtulGupta, ответ @theKarlo не заставляет подкласс передать IdRes.
Следовательно, альтернатива
@IdRes
abstract fun getHeaderId(): Int
и
@get:IdRes
abstract val headerId: Int
Это передать значение в конструктор самого класса, чтобы можно было избежать проблемы с полем поддержки и чтобы подкласс был вынужден передать IdRes.
Например:
abstract class SomeClass(@IdRes val idRes: Int)
Но в этом случае кто-то, использующий абстрактный класс, может обойти аннотацию, просто написав override
val headerId: Int = 5в своей реализации абстрактного класса.