【问题标题】:Kotlin - Extension for final classKotlin - 最终类的扩展
【发布时间】:2017-07-22 12:50:21
【问题描述】:

是否可以创建 final 类的扩展,例如 String?就像在 swift 中一样,可以在 extensionfinal class 中添加其他方法。

例如 - 我想在 String 扩展中创建一个方法,它会告诉我 String 的密码长度有效。

 val password : String = mEdtPassword!!.getText().toString()

 // how to define haveValidLength method in extension
 val isValid : Boolean = password.haveValidLength()

注意 - 该示例只是为了了解 extension 的可用性,而不是真实场景。

【问题讨论】:

    标签: kotlin kotlin-extension


    【解决方案1】:

    是的,你可以。 Kotin extension method 提供了用新功能扩展类的能力无需从类继承或使用任何类型的设计模式,例如装饰器。

    下面是String的扩展方法:

    //  v--- the extension method receiver type
    fun String.at(value: Int) = this[value]
    

    以及生成为Java的扩展方法代码如下:

    public static char at(String receiver, int value){
        return receiver.charAt(value);
    }
    

    所以 Kotlin 中的扩展方法是使用委托而不是继承。

    然后你可以像下面这样调用一个扩展方法作为它的成员函数:

    println("bar".at(1))//println 'a'
    

    你也可以为已有的扩展函数写一个扩展方法,例如:

    fun String.substring(value: Int): String = TODO()
    
    //    v--- throws exception rather than return "ar"
    "bar".substring(1)
    

    但是不能为已有的成员函数写扩展方法,例如:

    operator fun String.get(value: Int): Char = TODO()
    
    //   v--- return 'a' rather than throws an Exception
    val second = "bar"[1]
    

    【讨论】:

    • 感谢您的回复,我正在考虑添加一些额外的方法,而不是更新现有的方法。有可能吗?
    • @Rasi 我不更新现有的atString 没有 at 方法。上面的代码只是一个例子,先生。
    • @Rasi 您好,我已经添加了exntension方法的详细说明,您可以进一步查看。
    • 我试图回答一个可以帮助像我这样的初学者的基本水平。如果需要,请检查并建议编辑。再次感谢!
    • 您不能为现有的成员函数创建扩展。您示例中的 substring 实际上是 Kotlin 中的扩展本身,因此您可以选择要导入的扩展。如果它是一个成员函数,你不能使用你自己的扩展名,因为它被真正的函数“遮蔽”了。这在documentation 中也有解释
    【解决方案2】:

    尝试添加更多细节,此答案可能对某人有所帮助。

    是的,我们可以向final 类添加其他方法,例如String。例如,我想在String 中添加一个方法,它会告诉我我的String 是否有有效的密码字符数。

    所以我要做的是,我必须创建一个下面的函数,它可以写在同一个 class 或不同的单独 class 文件中。

        fun String.hasValidPassword() : Boolean {
    
     // Even no need to send string from outside, use 'this' for reference of a String
    
         return !TextUtils.isEmpty(this) && this.length > 6
        }
    

    现在可以从任何地方调用

        val isValid : Boolean = password.haveValidLength()
    

    建议

    如果您的应用程序只有一个密码验证,那么没有问题。

    但是,如果应用程序有多个验证,我不建议您编写这样的扩展方法hasValidPassword。由于扩展方法是satically,因此您无法在运行时更改您的hasValidPassword。所以如果你想在运行时改变验证,你应该使用一个函数来代替,例如:

    class PasswordRepository(private val validate:(String)->Boolean){
        fun save(value:String){
            if(validate(value)){
                //TODO persist the password
            }
        }
    }
    
    val permitAll = PasswordRepository {true}
    val denyAll = PasswordRepository {false}
    
    permitAll.save("it will be persisted")
    denyAll.save("it will not be persisted")
    

    也就是说,上面的扩展方法违反了Single Responsibility Principle,它做了验证和字符串操作。

    【讨论】:

    • 嗨,现在怎么样?你有什么困惑吗?我英文不好,希望你能看懂。
    • 感谢更新。我的意图只是展示如何在最终类中添加其他方法。无意使用任何一种这种方法。这是随机的例子。
    • 好吧。我投了赞成票,因为它符合您的意图。
    【解决方案3】:

    您可以使用 Kotlin 中的扩展函数来做到这一点。通过扩展,您可以为您可以访问或无法访问的类添加额外的功能;例如遗留代码库。在 Kotlin 文档 here 中给出的示例中,swap 被添加到 MutableList<Int> 中,而 swap 最初没有 swap。使用了this 关键字,它指代交换功能将对其进行操作的对象。在下面的示例中,this 指的是testList

    val testList = mutableListOf(1, 2, 3)
    testList.swap(0, 2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 2022-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多