Article Directory
Meet Kotlin
Like the java language, kotlin is compiled into bytecode and runs in the JVM virtual machine. The features of the kotlin language depend on kotlin's syntax compiler. Languages similar to kotlin are:
- Scala: The Big Data Domain Development Language
- Groovy: a dynamic scripting language based on the JVM platform,Used in Android development to write dependencies, plugins, etc.
In 2019, Google announced that Kotlin has become the first development language for Android, and it is imminent for Android programmers to switch from java to Kotlin.
cross-platform features
language type
Languages are divided into interpreted and compiled:
- Compiled language, the compiler will compile the source code into a binary file one at a time, and the computer can execute it directly, for example
C和C++
- Advantages: It can be run once compiled, no compilation is required during runtime, and the efficiency is high.
- Disadvantages: Different operating systems require different machine codes, and modifying the code requires recompiling module by module.
- Interpreted language, when the program is running, the interpreter will parse the source code line by line into binary in real time and execute it in the corresponding virtual machine, for example
JS、Python
- Advantages: The platform has good compatibility, and it can run after installing the corresponding virtual machine.
- Disadvantages: It needs to be interpreted and executed at runtime, and the efficiency is low.
java language type
Java is precisely a half-compiled and half-interpreted hybrid language, but it is more interpreted.
Java first compiles the source program into platform-independent Java bytecode (.class) through the compiler javac, and then interprets and executes the bytecode by the JVM.
How kotlin works
The JVM is only responsible for interpreting and executing the bytecode file.class, regardless of how the bytecode file is generated. Kotlin is based on this principle. It will be compiled into a class before running, and then run by the java virtual machine.
Kotlin不仅能够,还能脱离虚拟机层,直接编译成可以在Windows、Linux和MacOS平台上运行的原生二进制代码,被称为Android领域的Swift
hello world
The entry point of the Kotlin application is the main function main, which can take no parameters and return no value.
fun main() {
var str:String = "Hello World"
println(str)
}
basic concept
program entry
There can be no parameters or a parameter list, but the program entry has no return value.
fun main() {
}
fun main(args: Array<String>) {
}
Data and Object Types
In kotlin, the original basic data types in Java are cancelled, and all object types are used.
== and ===
Kotlin provides two ways to compare objects
- compare objects' structures for equality (
==
orequals
) - Compare object references for equality
===
fun main() {
//sampleStart
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a
val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
//sampleEnd
}
Since the JVM applies memory optimizations to integers from -128 to 127 (Integer), all nullable references to a are actually the same object. But no memory optimization is applied to b, so they are different objects ( ===
result is false).
On the other hand, their contents are still equal:
fun main() {
//sampleStart
val b: Int = 10000
println(b == b) // 输出“true”
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedB == anotherBoxedB) // 输出“true”
//sampleEnd
}
explicit number conversion
Smaller types in Kotlin cannot be implicitly converted to larger types, which means that assigning Byte
a type to a Int
variable must be explicitly converted:
fun main() {
val b : Byte = 1
val i1: Int = b.toInt();
}
All numeric types support conversion to other types:
- toByte(): Byte
- toShort(): Short
- toInt(): Int
- toLong(): Long
- toFloat(): Float
- toDouble(): Double
In many cases, explicit type conversion is not needed, because the type will be inferred from the context, and the arithmetic operation will be overloaded to do the appropriate conversion, for example:
val l = 1L + 3 // Long + Int => Long
floating point type
Kotlin provides floating-point types Float and Double types, which have different sizes and provide storage for floating-point numbers of two different precisions:
- For variables initialized with decimals, the compiler infers
Double
the type:
val pi = 3.14 // Double
// val one: Double = 1 // 错误:类型不匹配
val oneDouble = 1.0 //Double
- To explicitly specify a value as
Float
a type, addf
orF
suffix, and such a value will be rounded if it contains more than 6~7 decimal digits:
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float,实际值为 2.7182817
- Unlike other languages,Numbers in Kotlin do not have implicit widening conversions, for example functions with Double parameters can only be called on Double values, not on Float, Int or other numeric values:
fun main() {
fun printDouble(d: Double) {
print(d) }
val i = 1
val d = 1.0
val f = 1.0f
printDouble(d)
// printDouble(i) // 错误:类型不匹配
// printDouble(f) // 错误:类型不匹配
}
bit operation
Kotlin provides a set of bitwise operations for integer types Int
and .Long
- shl(bits) – signed left shift (shift left)
- shr(bits) – signed right shift (shift right)
- ushr(bits) – unsigned shift right
- and(bits) – bit and
- or(bits) – bits or
- xor(bits) – bit exclusive or
- inv() – bitwise inverse
Any
Any is the root type of a non-empty type, similar to Object as the top level of the Java class hierarchy. When Any类型是Kotlin中所有非空类型的超类。
Any is used in a Kotlin function, it will be compiled into an Object in the Java bytecode.
Any?类型是Kotlin所有类型的根类
At the bottom of the Kotlin type hierarchy is the Nothing type. The type structure diagram is as follows:
Unit
Unit
The function is similar to that in Java void
, but the meaning of void is that there is no return value. Kotlin is more thorough in facing objects. The return value without return value should also be an object, so there is Unit. If this concept is not
explicitly return
specified Return value, then the compiler will automatically add the return Unit
:
fun returnUnit() : Unit {
return Unit
}
Nothing
Unit
The meaning of this function is no return value.
However Nothing
, it isPrompt the developer that this function will not return, such as it 可能是抛异常
, does not return, or拥有无限循环的函数。
Function 1: The return value of the function that throws an exception
fun throwOnNameNull() : Nothing {
throw NullPointerException("姓名不能为空!")
}
In addition to the use of throwing an exception above, the ==Nothing object is also a common subtype of all object types. ==In this way, Nothing is actually multiple inheritance, that is, the inheritance rules are extended in Kotlin, 类不允许多重继承,Nothing除外
because the constructor of Nothing is private, it will not have any instance objects, so his multiple inheritance will not bring of any actual risk.
Based on the fact that Nothing is a subclass of all types, it can be combined with generics to build a generic empty List, as follows:
Function 2: As a generic, blank temporary filling for generic variables
Function 3: Nothing makes kotlin more complete at the grammatical level.
In the underlying logic of kotlin, throw has a return value, and its return value type is Nothing,
so the following writing is legal:
val nothing: Nothing = throw RuntimeException("抛异常!"
Because Nothing is a subclass of all types, all of the following works:
var _name: String? = null
val name: String = _name ?:throw NullPointerException("_name 运行时不能为空!")
declare variable
Kotlin uses keywords var
to declare variable variables, and the variable name and variable type are :
separated by a colon. This scripting language, like Python, does not require ;
an ending.
var
: Variable variable, corresponding to Java's 非fina
l variable
var b = 1
val
: Immutable variables, corresponding to Java final
variables
val a = 1
The above declaration process does not use a colon :
to indicate the type, because Kotlin has a class derivation mechanism, the above a
sum b
will be regarded as by default according to the assignment resultInt
Read-only variable val and mutable variable var
- var: Indicates a modifiable variable
- val: indicates a read-only variable
Mainly the difference between non-final and final.
View Kotlin bytecode
fun (method/function)
The fun keyword is used to declare methods:
Below is a method that takes 2 Int parameters and returns an Int.
fun sum(a: Int, b: Int): Int {
return a + b;
}
The method body can be an expression whose return value can be inferred:
fun sum (a: Int, b: Int) = a + b
The method can have no return value, or return a meaningless value (Unit)
fun printSum(a: Int, b:Int): Unit {
println("sum of $a and $b is ${
a + b}")
}
Among them, Unit can also be ignored;
fun printSum(a: Int, b:Int) {
println("sum of $a and $b is ${
a + b}")
}
Function parameter default values
Kotlin supports functions with default values, which are used as follows:
fun main() {
myPrint(1)
myPrint(1, "lalala")
}
fun myPrint(value : Int, str : String = "hello") {
println("num is $value, str is $str")
}
If the value wants to be the default value, it will be saved, because the first parameter passed in must be of type Int. The incoming string type will not match:
fun main() {
myPrint("zjm")//报错
}
fun myPrint(value: Int = 100, str: String) {
println("num is $value, str is $str")
}
Kotlin's function parameter passing supports the same key-value pair parameter passing as Python, so that the order of parameters can be changed:
fun main() {
myPrint(str = "zjm") //正确调用
}
fun myPrint(value: Int = 100, str: String) {
println("num is $value, str is $str")
}
class (class)
Define a
class The attributes of a class can be placed in the definition or inside the class, such as the following:
class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}
var rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${
rectangle.perimeter}")
For kotlin version 1.4.30, the inheritance of a class is :
represented by a colon. The class is final by default and cannot be inherited. In order to make the class inheritable, use open
keywords and place them in front of the class:
open class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}
$(string template)
Using $
templates that can help define strings, translate string variables.
To use variables directly $
, to use expressions, curly braces are required${}
Below is an example:
var a = 1
val S1 = "a is $a"
println(S1)
a = 2;
val S2 = "${
S1.replace("is", "was")}, but now is $a"
println(S2)
result:
a is 1
a was 1, but now is 2
control flow
if-else (conditional expression)
fun getMax(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
The if above can also be written as an expression, similar to the ternary operator:
fun getMax(a: Int, b: Int) = if (a > b) a else b
cycle
for
- use
in
keywords - use subscript
val items = listof("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
for (index in item.indices) {
println("item at $index is ${
items[index]}")
}
// 闭区间打印[1, 3]
// 输出 1,2,3
for (i in 1..3) {
println(i)
}
// 从7到0,降序,步长为2
// 输出 7,5,3,1
for (i in 7 downTo 0 step 2) {
println(i)
}
for- in
The default range is a double-closed range. If you want to use left-closed and right-open, you need to use keywordsuntil
fun main() {
for (i in 0 until 10) {
}
}
while
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
println("item at $index is ${
items[index++]}")
}
result:
item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit
when expression
when expression looks a bit like swich case in java.
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a String"
else -> "Unknown"
}
abnormal
Exception class Throwable
All exception classes in Kotlin inherit from classes and throw exceptions Throwable
using expressions:throw
fun main() {
//sampleStart
throw Exception("Hi There!")
//sampleEnd
}
Use try ... catch expressions to catch exceptions:
try {
// 一些代码
} catch (e: SomeException) {
// 处理程序
} finally {
// 可选的 finally 块
}
There can be zero or more catch blocks, and finally blocks can be omitted. But at least one catch and finally block is required.
Null values and null value checks
A variable that can be null requires a question mark after it ?
.
For example, the method below returns Int or null
fun parseInt(str: String) : Int? {
...
}
safe call operator?.
This operator allows you to combine a null check and a method call into one operation. For example
s?.toUpperCase()
Is equivalent to the following writing:
if (s!=null) {
s.toUpperCase
} else {
null
}
Safe calls can be used not only to call methods, but also to access properties.
If you have multiple properties of nullable types in your object, it is often convenient to use multiple safe calls in the same expression. Using this operator, you can access deeper properties in one line of code without additional checks. as follows:
class Address(val streetAddress:String,val code:Int,val city:String)
class Company(val name:String,val address: Address?)
class Person(val name:String,val company: Company?)
fun Person.cityName():String{
val city = this.company?.address?.city
return if (city != null) city else "unKnown"
}
Elvis operator?:
The Elvis operator takes two operands, and if the first operand is not null, the result of the operation is the first operand, otherwise the result of the operation is the second operand.
For example, below, if s is not empty, str is s, otherwise str is an empty string object
fun foo(s: String) {
val str: String = s?:""
}
The Elvis operator is often used with the safe call operator to replace the null returned by calling a method on a null object with a value. Let's simplify the previous code:
fun Person.cityName():String {
val city = this.company?.address?.city
return city ?: "unKnown"
}
There is a scene in kotlin where the Elvis operator is very suitable. Operations like return and throw are actually expressions, so they can be written on the right side of the Elvis operator. When the value to the left of the operator is null, the function immediately throws an exception.
fun printPersonName(person : Person) {
val name = person.name? : throw IllegalArgumetException("no name")
println(name)
}
Follow the conversionas?
as is a Kotlin operator used to convert types, just like java types, if the value being converted is not the type you are trying to convert. A ClassCastException will be thrown.
as?
operator attempts to convert the value to the specified type,Returns null if the value is not of the appropriate type. we canUse this operator with Elvis, such as implementing the equals method of the Person class
class Person(val name:String, val company: Company?) {
override fun equals(other: Any?): Boolean {
val otherPerson = other as? Person ?: return false
return otherPerson.name && other.company == company
}
}
non-null assertion!!
Non-null assertion is the most simple and direct tool provided by kotlin to deal with nullable type values. Use double exclamation marks to indicate that any value can be converted to a non-null type. An exception will be thrown if a non-null assertion is made on null.
fun ignoreNull(s:String){
val notNull = s!!
println(notNull.length)
}
If s is null in this function, an exception will be thrown at runtime. The place where the exception is thrown is the line where the not-null assertion is made, not the line where the value is then attempted to be used.
Because the information of the exception call stack trace only shows which line the exception occurred on,!!
To make trace information more explicit, avoid multiple assertions on the same line at the end .
let function
The let function makes it easier to work with nullable expressions. Used together with the safe call operator, it allows you to evaluate an expression, check if the result is null, and store the result in a variable, all of which all in the same simple expression.
What the let function does is to turn an object that calls it into a parameter of a lambda expression. Combined with the safe call syntax, it can effectively transform the nullable object that calls the let function into a non-null type. In other words,A let that is safe to call will only execute the lambda if the expression is not null.
s?.let {
print(s.length)
}
If you want to achieve the above effect, the Java code is as follows:
public static final void ignoreNull(@Nullable String s) {
if (s != null) {
System.out.print(s.length());
}
}
lateinit Lazy initialization properties
Kotlin usually requires that all properties be initialized in the constructor. If a property is a non-null property, a non-null initialization value must be provided, otherwise a nullable type must be used. If this is done, the property needs or asserts every time it is null检查
accessed !!
.
class MyService {
fun performAction():String = "foo"
}
class MyTest{
private var myService:MyService?=null
fun test() {
myService!!.performAction()
}
}
It can be used lateinit
to delay the initialization of myService. The properties of delayed initialization are all var. Although it is a non-null type, it does not need to be initialized in the constructor.
class MyService{
fun performAction():String = "foo"
}
class MyTest{
// 声明一个不需要初始化器的非空类型的属性
private lateinit var myService:MyService
fun test(){
myService.performAction()
}
}
Nullable type extension
The Kotlin standard library defines two extension functions of String isEmpty
, isBlank
isNullOrBlank
, to determine whether it is an empty string or whether it contains only blank characters. This extension function can allow the receiver to be called as null:
fun verifyInput(input:String?){
if (input.isNullOrBlank()){
print("it is not ok")
}
}
Safe access is not required because possible null values are handled internally by the function:
@kotlin.internal.InlineOnly
public inline fun CharSequence?.isNullOrBlank(): Boolean {
contract {
returns(false) implies (this@isNullOrBlank != null)
}
return this == null || this.isBlank()
}
Nullability of type parameters
The type parameters of all generic classes and generic functions in Kotlin are nullable by default, in which case null is allowed for declarations that use type parameters as types, even though the type parameter T does not end with a question mark.
fun <T> printSomething(t:T){
// 因为 t 可能为 null,所以必须使用安全调用
print(t?.hashCode())
}
// 传入 null 进行调用
printSomething(null)
In this method, the deduced type of the type parameter T is the nullable type Any?, so the actual parameter t still allows null even though it does not end with a question mark.
If the type parameter is non-null, you must specify a non-null upper bound for it, so that generics will reject nullable values as actual parameters.
// 这样的话,T 就不是可空的
fun <T:Any> printSomething1(t:T){
print(t.hashCode())
}
is: type checking and automatic conversion
It is usedis
to check whether an object is a certain type. If the type of an immutable variable is determined, then no explicit conversion is required when using it later:
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 这里obj已经转为String类型
return obj.length
}
return null
}
Or !is
write it in reverse:
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
return obj.length
}
classes and objects
Create a Person class:
class Person {
var name = ""
var age = 0
fun printInfo() {
println("name is $name, age is $age")
}
}
inherit
The default class in Kotlin is not inheritable (that is, it is modified by final). If you want this class to be inherited, you need class
to use open
the keyword before it.
open class Person {
var name = ""
var age = 0
fun printInfo() {
println("name is $name, age is $age")
}
}
Declare a Student class to inherit from the Person class. In kotlin, the inheritance uses :
the construction of the parent class:
class Student : Person() {
var number = ""
var grade = 0
fun study() {
println("$name is studying")
}
}
structure
The structure is divided into main structure and secondary structure
main structure
The main construction is written directly after the class
class Student(val number: String, val grade: Int) : Person() {
fun study() {
println("$name is studying")
}
}
Create a Student object:
val student = Student("1234", 90)
Because the parent class Person also has name and age attributes, a main structure is also constructed for the parent class Person:
open class Person(val name : String, val age : Int) {
fun printInfo() {
println("name is $name, age is $age")
}
}
At this time, Student reports an error, because when inheriting Person, the Person() no-argument construction is used later, and above we have modified Person's no-argument construction, so there is no no-argument construction.
class Student(name: String, age: Int, val number: String, val grade: Int) : Person(name, age){
fun study() {
println("$name is studying")
}
}
Construct a Student class at this time;
val student = Student("zjm", 20, "1234", 90)
What if construction requires special handling? Kotlin provides init
a structure, and the logic of the main structure can be processed in init, such as:
open class Person(val name : String, val age : Int) {
init {
println("name is $name")
println("age is $age")
}
}
The above modifications are all 主构造
, what if the class needs multiple constructs? Need help at this time次构造
secondary structure
Secondary construction, use constructor
the keyword to declare the constructor, :
followed by this()
, that isThe essence of the secondary constructor is to call the primary constructor
Implement the following two substructures:
- The construction of three parameters, name, age, number, grade does not pass parameters, the default is 0.
- No parameter construction: Int defaults to 0, String defaults to an empty string
class Student(name: String, age: Int, var number: String, var grade: Int) : Person(name, age){
fun study() {
println("$name is studying")
}
constructor(name: String, age: Int, number: String) : this(name, age, number, 0) {
}
constructor() : this("", 0, "", 0) {
}
}
// 调用
val student = Student("lzy", 23, "1234", 90)
val student1 = Student("lzy", 23, "121");
val student2 = Student()
permission modifier
The difference between Java and kotlin is as follows:
kotlin introduced internal
, abandoneddefault
Data classes and singleton classes
data class
The data class only deals with data-related, Java Bean
similar to and usually needs to implement its get
, set
, hashcode
, equal
, toString
and other methods.
The following implementation UserBean
includes: id
, name
, pwd
attributes.
Java:
public class UserBean {
private String id;
private String name;
private String pwd;
public UserBean() {
}
public UserBean(String id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserBean userBean = (UserBean) o;
return Objects.equals(id, userBean.id) && Objects.equals(name, userBean.name) && Objects.equals(pwd, userBean.pwd);
}
@Override
public int hashCode() {
return Objects.hash(id, name, pwd);
}
@Override
public String toString() {
return "UserBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
Writing this class in Kotlin will become very simple. Create a new kt
file and choose as follows:
one line of code can be done, and kotlin will automatically implement the above method.
Double-click on Shift to call up 工具搜索
, search show kotlin ByteCode
, and view the kotlin bytecode:
the corresponding Java Bean class is indeed created
singleton class
At present, the most widely used singleton mode (static inner class) in Java is implemented as follows:
public class SingleInstance {
private SingleInstance() {
}
private static class SingleHolder {
private static final SingleInstance INSTANCE = new SingleInstance();
}
public static SingleInstance getInstance() {
return SingleHolder.INSTANCE;
}
public void test() {
}
}
Kotlin
To create a singleton class in , you need to select the Object
generated code as follows:
object SingleInstance {
fun test () {
}
}
The corresponding java
files are as follows, similar to the above-mentioned most used java
singleton implementation:
public final class Singleton {
@NotNull
public static final Singleton INSTANCE;
public final void test() {
}
private Singleton() {
}
static {
Singleton var0 = new Singleton();
INSTANCE = var0;
}
}
Use as follows:
fun main() {
Singleton.test() //对应的java代码为Singleton.INSTANCE.test();
}
enum class
The most basic application scenario of an enumeration class is to implement a type-safe enumeration:
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
Each enumeration constant is an object. Enumeration constants are separated by commas.
Because every enumeration is an instance of the enumeration class, it can be initialized like this:
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
Every enumeration constant also has these two properties: name and ordinal, to get its name and position (from 0) in the enumeration class declaration:
enum class RGB {
RED, GREEN, BLUE }
fun main() {
//sampleStart
println(RGB.RED.name) // prints RED
println(RGB.RED.ordinal) // prints 0
//sampleEnd
}
Sealed class sealed
Define the Result interface:
interface Result
class Success(val msg: String) : Result
class Failure(val msg: String) : Result
Define a method:
fun getResultMsg(result: Result) = when(result) {
is Success -> result.msg
is Failure -> result.error.message
else -> throw IllegalArgumentException()
}
Due to the nature of Kotlin, else must be written, but the above code is only possible in two cases. else is purely redundant. If the programmer neglects to pass in the UnKown class, the APP will crash.
In order to solve the above problems, it is necessary to rely on sealed
the sealed class and its subclasses can only be defined at the top level of the same file, and cannot be nested in other classes
sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
fun getResultMsg(result: Result) = when(result) {
is Success -> result.msg
is Failure -> result.error.message
}
interface
Define an interface:
interface Study {
fun study()
fun readBooks()
fun doHomeWork()
fun exercise()
}
interface inheritance
The inherited interface only needs to be used behind the class ,
and implement Study
all the declared functions:
class GoodStudent(name: String, age: Int, var ID: String, var grade: Int) : Person(name, age) , Study{
override fun study() {
TODO("Not yet implemented")
}
override fun readBooks() {
TODO("Not yet implemented")
}
override fun doHomeWork() {
TODO("Not yet implemented")
}
override fun exercise() {
TODO("Not yet implemented")
}
}
Kotlin supports the default implementation of interface methods, and JDK1.8 later also supports this function. If the method has a default implementation, the inherited class does not have to implement this method.
interface Study {
fun study() {
println("study")
}
fun readBooks()
fun doHomework()
}
resolve overlay conflicts
When implementing multiple interfaces, you may encounter the problem of inheriting multiple implementations of the same method:
interface A {
fun foo() {
print("A") }
fun bar()
}
interface B {
fun foo() {
print("B") }
fun bar() {
print("bar") }
}
class C : A {
override fun bar() {
print("bar") }
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}
In the above example, interfaces A and B both define methods foo() and bar(). Both implement foo(), but only B implements bar() (bar() is not marked as abstract in A because it defaults to abstract when there is no method body in an interface). Now, if you implement a concrete class C of A, you must override bar() and implement this abstract method.
However, if you derive D from A and B, you need to implement all the methods inherited from multiple interfaces and indicate how D should implement them. This rule applies both to methods inheriting a single implementation ( bar() ) and to methods inheriting multiple implementations ( foo() ).
Functional Interface (SAM) Interface
An interface with only one abstract method is called a functional interface or a single abstract method (SAM) interface. A functional interface can have multiple non-abstract members, but only one abstract member.
For example, there is this Kotlin functional interface:
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
If you don't use SAM conversion, then you need to write code like this:
// 创建一个类的实例
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}
By taking advantage of Kotlin's SAM conversion, the following equivalent code can be changed instead:
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
val isEven = IntPredicate {
it % 2 == 0 }
fun main() {
println("Is 7 even? - ${
isEven.accept(7)}")
}