简体   繁体   中英

Abstract val with annotation in kotlin android

Can I write:

@IdRes
abstract fun getHeaderId(): Int

With a val instead of a fun in kotlin? It complains I need a backing field or delegate when i write:

@IdRes <-- errors
abstract val headerId: Int

Which is the most idiomatic in this case? One-liner with a fun or mess around with a backing field (I'm not used to backing fields, maybe it's change-resistance, i have never really used them so i think they are unpleasant)

Since abstract val or var is just a function without a backing field it cannot be annotated by IdRes annotation but there is a workaround. You can use it like this:

@get:IdRes
abstract val headerId: Int

EDIT:

Why does this works? We need to closer inspect IdRes annotation and its source code:

@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE})
public @interface IdRes {
}

As we can see this annotation can be used on methods, parameters, fields and local variables. When we use abstract val it's neither of those since it is abstract and we cannot have abstract fields in Java. Normally equivalent of abstract val something: Int in Java is:

private int something

public int getSomething() {
    return something;
}

From example, it's easy to see that the private field is what is called backing field of a property and you can't have those as abstract so that was the problem.

As mentioned in @AtulGupta comment, @theKarlo 's answer does not force the subclass to pass in an IdRes .

Therefore, an alternative to

@IdRes
abstract fun getHeaderId(): Int

and

@get:IdRes
abstract val headerId: Int

Is to pass the value into the constructor of the class itself, so that the backing field issue can be avoided.

For example:

abstract class SomeClass(@IdRes val idRes: Int)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM