Kotlin 继承和变量可见性
Kotlin inheritance and variables visibility
我遇到这种情况:
abstract class BaseWebClient(baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
val client = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
class AnimalsPortalClient(val config: Config, baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
fun getAnimals(): String {
return client.get( // ... etc
}
}
此解决方案不起作用,因为 - 当尝试从派生 class 中的覆盖 属性 检索 defaultHeaders
时 - 变量 config
是 null
.
一个可能的解决方案是将 config
object 传递给基础 class' 构造函数:
abstract class BaseWebClient(val config: Config, baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
// ... etc
}
class AnimalsPortalClient(localConfig: Config, baseUrl: String) : BaseWebClient(localConfig, baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
// ... etc
}
但此解决方案有一个缺点:并非所有扩展 classes 都需要配置 object。在大多数派生 class 中,我有空的默认值 headers。像这样:
class SoccerPortalClient(baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() = HttpHeaders()
使用我提出的解决方案,我将被迫始终有一个配置 object 传递给基础 class,即使不需要它。
所以基本上:
- 我对这个行为有点疑惑:为什么变量为空?是可见性问题,还是...?
- 解决这个问题的正确实施是什么?
谢谢!
问题是您在基础 class 中的 client
字段在其他任何事情之前被初始化。您可以延迟初始化它。像这样:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
您正在尝试访问 defaultHeaders
属性,此时派生 class 尚未初始化。
考虑将 client
属性 初始化程序转换为 getter:
val client
get() = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
或使用lazy delegate:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
我遇到这种情况:
abstract class BaseWebClient(baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
val client = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
class AnimalsPortalClient(val config: Config, baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
fun getAnimals(): String {
return client.get( // ... etc
}
}
此解决方案不起作用,因为 - 当尝试从派生 class 中的覆盖 属性 检索 defaultHeaders
时 - 变量 config
是 null
.
一个可能的解决方案是将 config
object 传递给基础 class' 构造函数:
abstract class BaseWebClient(val config: Config, baseUrl: String) {
abstract val defaultHeaders: HttpHeaders
// ... etc
}
class AnimalsPortalClient(localConfig: Config, baseUrl: String) : BaseWebClient(localConfig, baseUrl) {
override val defaultHeaders: HttpHeaders
get() {
val headers = HttpHeaders()
headers.add("app-name", config.appName)
headers.add("app-version", config.appVersion)
return headers
}
// ... etc
}
但此解决方案有一个缺点:并非所有扩展 classes 都需要配置 object。在大多数派生 class 中,我有空的默认值 headers。像这样:
class SoccerPortalClient(baseUrl: String) : BaseWebClient(baseUrl) {
override val defaultHeaders: HttpHeaders
get() = HttpHeaders()
使用我提出的解决方案,我将被迫始终有一个配置 object 传递给基础 class,即使不需要它。
所以基本上:
- 我对这个行为有点疑惑:为什么变量为空?是可见性问题,还是...?
- 解决这个问题的正确实施是什么?
谢谢!
问题是您在基础 class 中的 client
字段在其他任何事情之前被初始化。您可以延迟初始化它。像这样:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}
您正在尝试访问 defaultHeaders
属性,此时派生 class 尚未初始化。
考虑将 client
属性 初始化程序转换为 getter:
val client
get() = WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
或使用lazy delegate:
val client by lazy {
WebClient
.builder()
.baseUrl(baseUrl)
.defaultHeaders { it.addAll(defaultHeaders) }
.build()
}