本文介绍: [在这里插入图片描述](https://imgblog.csdnimg.cn/d2e3d9d474524bf4ade317818222b140.jpeg#pic_center)”世界上只有两种编程语言:一种经常被人喷,一种没人用。” ——现代原生移动应用主要由(iOS) 或者(Android) 编程语言开发。另外有两种主要的跨平台应用开发框架 —— React Native(JavaScript) 和 Flutter(Dart)。

hujiangtech.github.io/tech/android/2017/06/02/swiftvskotlincontrolflow.html

感受一下:

Dart

// Switch case 
var id = 5;
switch (id) {
  case 1:
    print("id == 1");
    break;
  case 2:
    print("id == 2");
    break;
  default:
    print("id is undefined");
}

// Inclusive for loop
for (var i = 1; i <= 5; i++) {}

// range match
// N/A

// Cascade notation (…)
querySelector(‘#confirm)
text = ‘Confirm
classes.add(important)
onClick.listen((e) =>
window.alert(‘Confirmed!’));

Kotlin

// When
val id = 5
when (id) {
  1 -> print("id == 1")
  2 -> print("id == 2")
else -> {
  print("id is undefined")
  }
}

// Inclusive for loop
for (index in 1..5) {}

// range match
val nb = 42
when (nb) {
in 0..7, 8, 9 -> println(single digit”)
10 -> println(double digits)
in 11..99 -> println(double digits)
in 100..999 -> println(“triple digits)
else -> println(four or more digits)
}

// Cascade notation (…)
// N/A,可以用 Builder 模式或者 apply, also 函数

Swift

// Switch case
let id = 5
switch id {
  case 1:
    print("id == 1")
  case 2:
    print("id == 2")
  default:
    print("id is undefined")
}

// Inclusive for loop
for index in 1.5 {}

// range match
let nb = 42
switch nb {
case 0.7, 8, 9: print(single digit”)
case 10: print(double digits)
case 11.99: print(double digits)
case 100.999: print(“triple digits)
default: print(“four or more digits”)
}

// Cascade notation (…)
// N/A,用 Builder 或者 apply{} 扩展

总结Kotlin,Swift控制流都各有许多减少代码量,增加代码清晰度的花样。比如 Kotlin 用增强版的 when 取代了 switch ,if 和 when 不仅可做控制语句,也可作表达式使用。Swiftswitch 语句支持元组where 语句添加额外判断等。

Dartswitch 跟 Java 一样,需要主动 break,Swift 则相反,匹配到则自动退出 switch ,想要显式继续执行的话要用 fallthrough

Dart 的级联注记 (Cascade notation) 也算它的一个小特色了,不过其他语言也有各自的替代方案严格说来,它并不算一个操作符,只是 Dart 的一种特殊语法。笔者自己在写 Java 代码时也封装 API 做过类似的操作。这种书写方式最大的好处是:把一堆高度相关的代码逻辑强制”聚在一处,使代码看起来更流畅,整洁。


函数

Dart

String greet(String name, String day) {
    return "Hello $name, today is $day.";
}
greet("Bob", "Tuesday");

Kotlin

fun greet(name: String, day: String): String {
    return "Hello $name, today is $day."
}
greet("Bob", "Tuesday")

Swift

func greet(_ name: String, _ day: String) -> String {
    return "Hello (name), today is (day)."
}
greet("Bob", "Tuesday")

总结:Swift 和 Kotlin 都是类型后置的风格,注意 Swift 返回值用 -> , Kotlin 仍是用冒号。

下划线在 Swift 中有许多用法,其中有一类主要是“忽略”,包括忽略元组元素循环局部变量,以及函数中外部参数名。Standard Library 中有大量 API 的第一个参数都是可以忽略外部参数名的。

Kotlin 用 fun,Swift 用 func,Dart 和 Java ,C 等语言一样,没有为函数声明引入额外关键字

可变数量的参数

Dart

N/A

Kotlin

fun sumOf(vararg numbers: Int): Int {     
    var sum = 0
    for (number in numbers) {         
        sum += number     
    }     
    return sum
}
sumOf(42, 597, 12)

一个 Kotlin 函数只能有一个可变数量的参数。对于顺序没有强制约束可以放在普通参数之前或者之后。当同时包含可变参数和普通参数时,调用时普通参数需要使用命名参数的调用语法

fun sumOfNumbers(vararg numbers: Double, initialSum: Double): Double {
    var sum = initialSum
    for(number in numbers) {
        sum += number
    }
    return sum
}
sumOfNumbers(1.5, 2.5, initialSum=100.0) // Result = 104.0

Swift

func sumOf(_ numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf(42, 597, 12)

可变数量的参数在 Swift 官方文档称为 variadic parameter 。同样,一个函数只允许至多一个 variadic parameter 。

函数类型

Dart

// 写法1
int Function(int) makeIncrementer(int a) {
    return (a) {
        return 1 + a;
    };
}

// 写法2
int Function(int) makeIncrementer2(int a) {
int myInnerFunction(a) {
return 1 + a;
}

<span class="kd">final</span> <span class="n">myFunction</span> <span class="o">=</span> <span class="n">myInnerFunction</span><span class="p">;</span>
<span class="k">return</span> <span class="n">myFunction</span><span class="p">;</span>

}

// 写法3:类型是 Closure: (int) => int
int Function(int) increment = (int a) {
return 1 + a;
};

// 写法4:类型是 Closure: (dynamic) => num
var increment2 = (a) {
return 1 + a;
};

print(makeIncrementer);
print(makeIncrementer(1));
print(makeIncrementer(1)());

print(increment);
print(increment(1));

Kotlin

fun makeIncrementer(): (Int) -> Int {     
    val addOne = fun(number: Int): Int {         
        return 1 + number     
    }     
    return addOne 
} 
val increment = makeIncrementer() 
increment(7)

// makeIncrementer 可以写成更短的形式
fun makeIncrementer2() = fun(number: Int) = 1 + number

Swift

func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
let increment = makeIncrementer()
increment(7)

总结在这几种语言中,函数都是一等公民。Swift 是中规中矩的写法,Kotlin 提供了简短的版本。Dart 也有几种写法。当然,写法 1、2 和写法 3 、4 并不对等,推荐 3、4 的写法。留意结尾的分号,这里没有分号结尾的差别类似于 C++ 中的声明定义。写法1、2 仅声明,写法 3、4 声明的同时也定义了,所以必须加分号。

映射

Dart

final numbers = [20, 19, 7, 12];

// 写法1
numbers.map((number) => 3 * number).toList();

// 写法2:类似 Python 的语法
[for (var number in numbers) 3 * number];

Kotlin

val numbers = listOf(20, 19, 7, 12)
numbers.map { 3 * it }

Swift

let numbers = [20, 19, 7, 12]
numbers.map { 3 * $0 }

排序

Dart

var list = [1, 5, 3, 12, 2];
list.sort();

Kotlin

listOf(1, 5, 3, 12, 2).sorted()

Swift

var mutableArray = [1, 5, 3, 12, 2].sorted()

命名参数

Dart

// Dart 的命名参数同时也是可选参数,用 {} 包裹
int area({int width, int height}) {
    return width * height;
}

area(width: 2, height: 3)
// 命名参数可以任意顺序书写
area(height: 3, width: 2)

// Dart 的可选顺序参数,用 [] 包裹
int area([int width, int height]) {
return width * height;
}

area(); // 可编译运行错误
area(2); // 可编译运行错误
area(2, 3); // OK

Kotlin

fun area(width: Int, height: Int) = width * height
area(width = 2, height = 3)

// 混合顺序参数和命名参数的写法
area(2, height = 3)

// 全部采用命名参数时可以任意顺序书写
area(height = 3, width = 2)

Swift

func area(width: Int, height: Int) -> Int {
    return width * height
}
area(width: 2, height: 3)

总结:Swift 的参数列表设计最为严格,参数需要同时匹配顺序名称 (命名的作用仅仅只是为了使代码含义更清晰) 。Kotlin 类似 Python,纯命名参数方式可以随意调整顺序,意味着开发者记忆 API 不需要记顺序。 Dart 的命名参数同时也是可选参数。

当然,得益于强大的现代集成开发环境,准确记忆 API 的完整参数列表这种需求对大多数程序员是不存在的。


声明定义

Dart

class Shape {
    var numberOfSides = 0;
    String simpleDescription() {
        return "A shape with $numberOfSides sides.";
    }
}

var shape = Shape();
shape.numberOfSides = 7;
var shapeDescription = shape.simpleDescription();

Kotlin

class Shape {
    var numberOfSides = 0
    fun simpleDescription() =
        "A shape with $numberOfSides sides."
}

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

Swift

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with (numberOfSides) sides."
    }
}

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

继承

Dart

class NamedShape {
    int numberOfSides = 0;
    String name;
<span class="n">NamedShape</span><span class="p">(</span><span class="kt">String</span> <span class="n">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// 或者采用语法糖写法

NamedShape(this.name);

<span class="kt">String</span> <span class="n">simpleDescription</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s2">"A shape with </span><span class="si">$</span><span class="n">numberOfSides</span><span class="s2"> sides."</span><span class="p">;</span>
<span class="p">}</span>

}

class Square extends NamedShape {
double sideLength;

<span class="n">Square</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">sideLength</span><span class="p">,</span> <span class="kt">String</span> <span class="n">name</span><span class="p">)</span> <span class="o">:</span> <span class="k">super</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">numberOfSides</span> <span class="o">=</span> <span class="m">4</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">double</span> <span class="n">area</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">sideLength</span> <span class="o">*</span> <span class="n">sideLength</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// Dart 官方建议审慎使用 @override 注解,当超类不在自身控制下时使用

// 这个注解主要是为了超类更改了代码,子类不知情仍正常工作可以提醒程序员
@override
String simpleDescription() {
return “A square with sides of length $sideLength.”;
}
}

final test = Square(;5.2, “square”);
print(test.area());
print(test.simpleDescription());

Kotlin

open class NamedShape(val name: String) {
    var numberOfSides = 0
<span class="k">open</span> <span class="k">fun</span> <span class="nf">simpleDescription</span><span class="p">()</span> <span class="p">=</span>
    <span class="s">"A shape with $numberOfSides sides."</span>

}

class Square(var sideLength: BigDecimal, name: String) :
NamedShape(name) {
init {
numberOfSides = 4
}

<span class="k">fun</span> <span class="nf">area</span><span class="p">()</span> <span class="p">=</span> <span class="n">sideLength</span><span class="p">.</span><span class="n">pow</span><span class="p">(</span><span class="m">2</span><span class="p">)</span>

<span class="k">override</span> <span class="k">fun</span> <span class="nf">simpleDescription</span><span class="p">()</span> <span class="p">=</span>
    <span class="s">"A square with sides of length $sideLength."</span>

}

val test = Square(BigDecimal(“5.2”), “square”)
println(test.area())
println(test.simpleDescription())

Swift

class NamedShape {
    var numberOfSides: Int = 0
    let name: String
<span class="kd">init</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="p">{</span>
    <span class="kc">self</span><span class="p">.</span><span class="n">name</span> <span class="p">=</span> <span class="n">name</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">simpleDescription</span><span class="p">()</span> <span class="p">-&amp;gt;</span> <span class="nb">String</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s">"A shape with </span><span class="si">(</span><span class="n">numberOfSides</span><span class="si">)</span><span class="s"> sides."</span>
<span class="p">}</span>

}

class Square: NamedShape {
var sideLength: Double

<span class="kd">init</span><span class="p">(</span><span class="n">sideLength</span><span class="p">:</span> <span class="nb">Double</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="p">{</span>
    <span class="kc">self</span><span class="p">.</span><span class="n">sideLength</span> <span class="p">=</span> <span class="n">sideLength</span>
    <span class="kc">super</span><span class="p">.</span><span class="kd">init</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">name</span><span class="p">)</span>
    <span class="kc">self</span><span class="p">.</span><span class="n">numberOfSides</span> <span class="p">=</span> <span class="mi">4</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">area</span><span class="p">()</span> <span class="p">-&amp;gt;</span> <span class="nb">Double</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">sideLength</span> <span class="o">*</span> <span class="n">sideLength</span>
<span class="p">}</span>

<span class="kr">override</span> <span class="kd">func</span> <span class="nf">simpleDescription</span><span class="p">()</span> <span class="p">-&amp;gt;</span> <span class="nb">String</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s">"A square with sides of length "</span> <span class="o">+</span>
       <span class="nb">String</span><span class="p">(</span><span class="n">sideLength</span><span class="p">)</span> <span class="o">+</span> <span class="s">"."</span>
<span class="p">}</span>

}

let test = Square(sideLength: 5.2, name: “square”)
print(test.area())
print(test.simpleDescription())

总结继承的书写方式在各种编程语言中可谓五花八门。像 Python 是将父类放在 () 里紧跟在子类名后,Ruby 是用 < 。典型的 C 家族是用 :。现代编程语言主要在构造器上玩一些花样。其中 Kotlin 的花样特别多,分为主从两类构造器,主构造器必有 (没声明的话会默认生成无参的 public 主构造器) ,主构造器隐含初始化块等。写法上主构造器是直接跟在类头

// Kotlin
class NamedShape constructor(val name: String) { /*……*/ }
// 如果主构造函数没有任何注解或者可见性修饰符可以省略这个 constructor 关键字

Swift 的 init 其实也挺复杂可以参考下面这篇文章

关于
override个人更喜欢 Kotlin 和 Swift 把它们作为关键字的做法。这样在编译期就能够明确开发者的意图。其一避免本不想重写但不小心重写的情况,其二显式书写确保重写方法存在,即正确重写了。

类型检查

Dart

final test = Square(5.2, "square");
if (test is Square) {
    print("test is square.");
}

if (test is! Square) {
print(“test is not square.”);
}

// 获取类型
print(test.runtimeType);

Kotlin

val test = Square(BigDecimal("5.2"), "square")
if (test is Square) {
    println("test is square.")
}
if (test !is Double) {
    println("test is not square.")
}

// 获取类型
println(test.javaClass.kotlin);

Swift

let test = Square(sideLength: 5.2, name: "square")
if (test is Square) {
    print("test is square.")
}
if !(test is Double) {
    print("test is not square.")
}

// 获取类型
print(type(of: test));

接口协议编程

Dart

// 被声明为 abstract 因此不能被实例abstract class AbstractContainer {
  // 定义构造器, 字段, 方法...

  void updateChildren(); // Abstract method.
}

// Dart 移除显式接口声明,
// 每个类都隐式的定义个了一个包该类该类实现的接口的所有实例成员
// (说人话:类就是接口)。
// 一个通过 implements 语句声明它们实现一个或者多个接口,
// 然后提供接口要求的 API,例如

// Person. 包含了 greet() 方法的隐式接口
class Person {
// 仅库可见,属于接口的一部分
final _name;

<span class="c1">// 不属于接口的一部分,因为这是个构造器

Person(this._name);

<span class="c1">// 属于接口的一部分

String greet(String who) => ‘Hello,

<

/

s

p

a

n

>

<

s

p

a

n

c

l

a

s

s

=

n

>

w

h

o

<

/

s

p

a

n

>

<

s

p

a

n

c

l

a

s

s

=

s

1

>

.

I

a

m

<

/

s

p

a

n

>

<

s

p

a

n

c

l

a

s

s

=

s

i

>

</span><span class=”n”>who</span><span class=”s1″>. I am </span><span class=”si”>

</span><spanclass=n>who</span><spanclass=s1″>.Iam</span><spanclass=si>_name.’;
}

// 一个 Person 接口的实现
class Impostor implements Person {
get _name => ‘’;

<span class="kt">String</span> <span class="n">greet</span><span class="p">(</span><span class="kt">String</span> <span class="n">who</span><span class="p">)</span> <span class="o">=&amp;gt;</span> <span class="s1">'Hi </span><span class="si">$</span><span class="n">who</span><span class="s1">. Do you know who I am?'</span><span class="p">;</span>

}

String greetBob(Person person) => person.greet(‘Bob’);

void main() {
print(greetBob(Person(‘Kathy’)));
print(greetBob(Impostor()));
}

// 如果想要像 Java 那样的接口,建议抽象类作为接口,相当于是把关心的部分提炼出来

Kotlin

interface Nameable {
    fun name(): String
}

fun <T: Nameable> f(x: T) {
println(“Name is “ + x.name())
}

class NameX : Nameable {
override fun name() : String {
return “NameX”;
}
}

f(x = NameX())

Swift

protocol Nameable {
    func name() -> String
}

func f<T: Nameable>(x: T) {
print(“Name is “ + x.name())
}

class NameX: Nameable {
func name() -> String {
return “NameX”;
}
}

f(x: NameX())


Lambda 表达式闭包

lambda 表达式简单理解匿名函数,它是“函数字面值”,即未声明的函数, 但立即做为表达式传递。闭包,简单理解为持有外部环境变量的函数。两者都是函数,并非所有的匿名函数都是闭包,也并非所有的闭包都是匿名的。

Dart

// 匿名函数标准形式
// ([[Type] param1[, …]]) { 
//  codeBlock; 
// }; 
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

Kotlin

// Lambda 表达式标准形式
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
println(sum(1, 2))

// 拖尾 lambda 表达式
// 如果函数的最后一个参数是函数,那么作为相应参数传入的 lambda 表达式可以放在圆括号之外:
val product = items.fold(1) { acc, e -> acc * e }

// 唯一参数 lambda 表达式
// 如果该 lambda 表达式是调用唯一的参数,那么圆括号可以完全省略:
run { println(“…”) }

Swift

// 闭包表达式标准形式
// { (parameters) -> return type in
//    statements
// }
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

// 拖尾闭包
// 如果函数的最后一个参数是函数,那么作为相应参数传入的闭包表达式可以放在圆括号之外:
reversedNames = names.sorted() { $0 > $1 }

// 唯一参数闭包
// 如果该闭包是调用唯一的参数,那么圆括号可以完全省略
reversedNames = names.sorted { $0 > $1 }


原文地址:https://blog.csdn.net/weixin_43959963/article/details/128643755

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_41790.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注