伴生对象与多态

package com.tencent.bk.devops.atom.task.repository import com.tencent.bk.devops.atom.task.utils.RepoAuthType data class CodeBitbucketRepository( override val aliasName: String, override val url: String, override val credentialId: String, override val projectName: String, override val userName: String, val authType: RepoAuthType? = RepoAuthType.SSH, override val projectId: String?, override val repoHashId: String? ) : Repository { companion object { // const val classType = "codeGitLab" const val classType = "gitlab" } override fun getStartPrefix() = "git@git.code.oa.com" override fun isLegal() = true }
 
 
详细解释一下 companion object { // const val classType = "codeGitLab" const val classType = "gitlab" }
 
 
 
 
companion object 是 Kotlin 中的一种机制,用来在类中定义一个伴生对象(Companion Object)。伴生对象的成员类似于 Java 中的静态成员(static members),即它们属于类而不是某个具体的实例。使用伴生对象可以在不创建类实例的情况下访问其成员。

在你的代码中,伴生对象的定义如下:

kotlin
companion object { // const val classType = "codeGitLab" const val classType = "gitlab" }

下面是对这段代码的详细解释:

  1. companion object:

    • 这表示定义一个伴生对象。伴生对象的名字可以省略,默认名字是 Companion
    • 伴生对象中的成员可以通过类名直接访问,无需实例化类。
  2. const val classType = "gitlab":

    • const val 是 Kotlin 中用于定义编译时常量(compile-time constant)的关键字。
    • classType 是一个常量属性,它的值是字符串 "gitlab"
    • 这意味着 classType 是一个不可变的常量,并且可以在编译时确定其值。
  3. 被注释掉的代码 // const val classType = "codeGitLab"

    • 这是被注释掉的代码行,表示之前 classType 的值是 "codeGitLab"。注释掉它可能是因为不再需要这个值,或者是为了保留历史记录。

在实际使用中,这个 classType 常量可以在 JsonSubTypes 注解中用于标识 CodeBitbucketRepository 类型。例如:

kotlin
@JsonSubTypes( JsonSubTypes.Type(value = CodeBitbucketRepository::class, name = CodeBitbucketRepository.classType) )

在上述注解中,CodeBitbucketRepository::class 表示 CodeBitbucketRepository 类,而 CodeBitbucketRepository.classType 使用了伴生对象中的 classType 常量作为标识符。这种做法使代码更具可读性和可维护性,因为标识符集中在一个地方定义,可以避免硬编码字符串散布在代码中。

总结:

  • companion object 定义了一个伴生对象,使得 classType 常量可以通过类名直接访问。
  • const val classType = "gitlab" 定义了一个编译时常量。
  • 伴生对象的这种用法有助于更好地组织代码,使标识符和常量更容易管理和维护。
 
 
package com.tencent.bk.devops.atom.task.repository import com.fasterxml.jackson.annotation.JsonSubTypes import com.fasterxml.jackson.annotation.JsonTypeInfo @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonSubTypes( JsonSubTypes.Type(value = CodeBitbucketRepository::class, name = CodeBitbucketRepository.classType) ) interface Repository { val aliasName: String val url: String val credentialId: String val projectName: String val userName: String val projectId: String? val repoHashId: String? // svn start with svn+ssh:// fun isLegal() = url.startsWith(getStartPrefix()) fun getStartPrefix(): String fun getFormatURL() = url } 详细解释一下@JsonSubTypes( JsonSubTypes.Type(value = CodeBitbucketRepository::class, name = CodeBitbucketRepository.classType) )
ChatGPT

@JsonSubTypes 注解用于指定在反序列化时可用的子类型。这个注解通常与 @JsonTypeInfo 一起使用,以支持多态类型的序列化和反序列化。它允许 Jackson 库根据类型信息正确地实例化具体的子类。

在你的代码中:

kotlin
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") @JsonSubTypes( JsonSubTypes.Type(value = CodeBitbucketRepository::class, name = CodeBitbucketRepository.classType) ) interface Repository { val aliasName: String val url: String val credentialId: String val projectName: String val userName: String val projectId: String? val repoHashId: String? fun isLegal() = url.startsWith(getStartPrefix()) fun getStartPrefix(): String fun getFormatURL() = url }

这里有两个注解:@JsonTypeInfo@JsonSubTypes,我们来详细解释它们。

@JsonTypeInfo

kotlin
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
  • use:指定类型信息的使用方式。JsonTypeInfo.Id.NAME 表示使用类型名称。
  • include:指定类型信息的包含方式。JsonTypeInfo.As.PROPERTY 表示将类型信息作为一个属性包含在 JSON 对象中。
  • property:指定类型信息的属性名称。在这个例子中,类型信息会作为 @type 属性包含在 JSON 中。

@JsonSubTypes

kotlin
@JsonSubTypes( JsonSubTypes.Type(value = CodeBitbucketRepository::class, name = CodeBitbucketRepository.classType) )
  • 这个注解定义了一个多态类型的子类型映射,使得 Jackson 能够在反序列化时根据 @type 属性的值来实例化具体的子类。
  • JsonSubTypes.Type:这是一个内部类,用于指定子类型映射。
    • value:指定具体的子类。在这个例子中是 CodeBitbucketRepository::class,表示 CodeBitbucketRepository 类。
    • name:指定子类型的名称。在这个例子中使用了 CodeBitbucketRepository.classType,其值是 "gitlab"

具体使用场景

假设你有以下 JSON 数据:

json
{ "@type": "gitlab", "aliasName": "MyRepo", "url": "http://example.com/repo.git", "credentialId": "12345", "projectName": "Project", "userName": "User", "projectId": "67890", "repoHashId": "abcde" }

当 Jackson 反序列化这个 JSON 数据时,它会查看 @type 属性的值,发现是 "gitlab"。然后,它会使用 JsonSubTypes 注解中定义的映射来决定实例化 CodeBitbucketRepository 类,并将 JSON 数据映射到这个类的实例中。

为什么这样使用

  1. 多态支持:使用 @JsonTypeInfo@JsonSubTypes 注解可以使 Jackson 支持多态类型的序列化和反序列化。在处理复杂对象结构时,这非常有用。
  2. 可扩展性:你可以轻松地添加新的子类型,只需在 @JsonSubTypes 注解中添加新的映射即可。
  3. 避免硬编码:通过使用 classType 常量,可以避免在多个地方硬编码类型名称,提高代码的可维护性。

总结:

  • @JsonTypeInfo 定义了类型信息的使用方式和包含方式。
  • @JsonSubTypes 定义了多态类型的子类型映射,使得 Jackson 能够正确地实例化具体的子类。
  • 这种组合使用可以帮助 Jackson 在处理多态类型时更灵活和可扩展。
posted @ 2024-05-27 16:03  小白冲  阅读(8)  评论(0编辑  收藏  举报