快速提示:使用Kotlin SAM转换编写更清洁的代码

如果您是一位经验丰富的Android应用程序开发人员,您可能已经习惯Java 7的冗长了。因此,您可能会发现Kotlin的简洁语法(该语言适用于函数式程序员)略有不安。

初学者在学习Kotlin时遇到的一个常见问题是了解如何期望您使用包含单个方法的Java接口。 这样的接口在Android世界中无处不在,通常被称为SAM接口,其中SAM是Single Abstract Method的缩写。

在这个简短的教程中,您将学到在Kotlin代码中恰当地使用Java的SAM接口所需的一切。

1.什么是SAM转换?

当您想使用Kotlin代码中包含单个方法的Java接口时,不必手动创建实现该方法的匿名类。 相反,您可以使用lambda表达式。 由于有一个称为SAM转换的过程,Kotlin可以将其签名与接口的单个​​方法的签名匹配的任何lambda表达式透明地转换为实现该接口的匿名类的实例。

例如,考虑以下一种方法的Java接口:

public interface Adder {
    public void add(int a, int b);
}

使用上述接口的一种幼稚且类似于Java 7的方法将涉及使用object表达式,并且看起来像这样:

// Creating instance of an anonymous class
// using the object keyword
val adder = object : Adder {
    override fun add(a: Int, b: Int): Int {
        return a + b
    }
}

那是很多不必要的代码,也不太可读。 但是,通过利用Kotlin的SAM转换工具,您可以编写以下等效代码:

// Creating instance using a lambda
val adder = Adder { a, b -> a + b }

如您所见,我们现在用一个简短的lambda表达式替换了匿名类,该表达式以接口名称为前缀。 请注意,lambda表达式采用的参数数量等于接口方法签名中的参数数量。

2.函数调用中的SAM转换

使用具有以SAM类型作为参数的方法的Java类时,可以进一步简化上述语法。 例如,考虑下面的Java类,该类包含一个期望实现Adder接口的对象的方法:

public class Calculator {
    private Adder adder;

    public void setAdder(Adder adder) {
        this.adder = adder;
    }

    public void add(int a, int b) {
        Log.d("CALCULATOR", "Sum is " + adder.add(a,b));
    }
}

现在,在您的Kotlin代码中,您可以直接将lambda表达式传递给setAdder()方法,而无需在其前面加上Adder接口的名称。

val calculator = Calculator()
calculator.setAdder({ a, b -> a+b })

值得注意的是,在调用以SAM类型作为唯一参数的方法时,您可以随意跳过括号以使代码更加简洁。

calculator.setAdder { a, b -> a+b }

3.不带Lambda的SAM转换

如果您认为lambda表达式令人困惑,那么我对您来说是个好消息:SAM转换也可以与普通函数一起正常工作。 例如,考虑以下函数,其签名与Adder接口的方法的签名匹配:

fun myCustomAdd(a:Int , b:Int):Int =
    if (a+b < 100)
        -1
    else if (a+b < 200)
        0
    else
        a+b

Kotlin允许您直接将myCustomAdd()函数作为参数传递给Calculator类的setAdder()方法。 不要忘记使用::运算符来引用该方法。 这是如何做:

calculator.setAdder (this::myCustomAdd)

4. it变量

SAM接口很多时候都包含一参数方法。 顾名思义,单参数方法的签名中只有一个参数。 在使用此类接口时,Kotlin允许您省略lambda表达式签名中的参数,并在表达式的主体中使用称为it的隐式变量。 为了使事情更清楚,请考虑以下Java接口:

public interface Doubler {
    public int doubleIt(int number);
}

在Kotlin代码中使用Doubler接口时,无需在lambda表达式的签名中明确提及number参数。 相反,您可以简单地将其称为it

// This lambda expression using the it variable
val doubler1 = Doubler { 2*it }

// is equivalent to this ordinary lambda expression
val doubler2 = Doubler { number -> 2*number }

5. Kotlin中的SAM接口

作为Java开发人员,您可能倾向于在Kotlin中创建SAM接口。 但是,这样做通常不是一个好主意。 如果您在Kotlin中创建SAM接口,或创建一个Kotlin方法(期望将实现SAM接口的对象作为参数),则SAM转换工具将不可用-SAM转换是Java的互操作性功能,并且仅限于Java类和接口。

由于Kotlin支持高阶函数(可以将其他函数作为参数的函数),因此您无需在其中创建SAM接口。 例如,如果用Kotlin重写Calculator类,则可以将其setAdder()方法编写为直接将函数作为参数,而不是实现Adder接口的对象。

class Calculator {
    var adder:(a:Int, b:Int)->Int = {a,b -> 0} 
                                    // Default implementation
                                    // Setter is available by default

    fun add(a:Int, b:Int) {
        Log.d("CALCULATOR", "Sum is " + adder(a,b))
    }
}

在使用上述类时,可以使用=运算符将adder设置为函数或lambda表达式。 以下代码向您展示了如何:

val calculator = Calculator()
calculator.adder = this::myCustomAdd
// OR
calculator.adder = {a,b -> a+b}

结论

Android的API主要是用Java编写的,许多API广泛使用SAM接口。 大多数第三方库也可以这样说。 通过使用在本教程中学到的技术,您可以以简洁易懂的方式在Kotlin代码中使用它们。

翻译自: https://code.tutsplus.com/tutorials/quick-tip-write-cleaner-code-with-kotlin-sam-conversions--cms-29304

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值