本文正在参与「金石方案」

前语

最近学习Flutter,发现其运用的Dart言语,有些方面很像Java,有些方面又很像Kotlin,所以整理下目前发现的差异点,一方面便利自己回忆,另一方面也期望能够给尚未触摸过Flutter小伙伴们供给一些协助。(本文仅从Dart言语运用角度对比Java & Kotlin。)

1. 根本数据类型

Dart中,只有三种根本数据类型,数字型(num),布尔型(bool),字符串类型(String)。容器类型如List ,Map,是否归于根本数据类型,这里暂不评论,毕竟运用也很简单。

类型 Dart Java Kotlin
布尔 bool boolean Boolean
数字 num (int / double) int / double / long / char /byte … Int / Double /Long / Char / Byte…
字符串 String String String

1.1 数字类型

  • num 在Dart 中为抽象类,具有intdouble两个完成类,运用num 为类型界说变量时,会进行变量类型揣度,揣度为对应的完成类(int/ double)。

        ///其间需求留意,Dart中num 相同能够作为数据类型运用,如:
        num a = 10; (整数型)
        num b = 10.0; (浮点型)  
        int c = 10; (整数型)
        double d = 10.00; (浮点型)
    
  • int 类型不只能够表明整形数字,还代表byte 及 char类型数据,详细运用办法如下:

        ///byte 类型
        int x = 65;
        print(x.toRadixString(2));// 输出 1000001
        ///char 类型
        List<int> codes = [65, 66];
        for(var element in codes) {
            print(String.fromCharCode(element); //输出 AB
        }
    

1.2 字符串类型

  • 先看下Dart中字符串的界说,大概与Java 和 Kotlin相同:

      字符串界说:
      ///单引号界说字符串
      String e = 'hello world';
      String g = '''hello world''';
      ///双引号界说字符串
      String f = "hello world";
      String h = """hello world""";
    
  • 其间运用三引号'''"""时,会跟随文本换行,而双引号与单引号""''不会,单引号主动换行需求借助\n换行符。单引号界说的字符串中能够包括双引号,双引号界说的字符串中能够包括单引号, 同类引号中无法包括同类引号,如:

        错误运用:
        String a = "----"hello world"----";
        String b = '----'hello world'----';
        正确运用:
        String a = '----"hello world"----';
        String b = "----'hello world'----";
    
  • Dart 支持 Kotlin 字符串拼接办法:

        String name = "Child";
        String s = "$name, hello world, ${name}"
    

2.语法差异

Dart的语法与Java根本是相同的,只不过在细节上有些差异,Dart在Java基础上,进行了优化。Dart在Java基础上,进行了优化,使其愈加简洁,便利。

2.1 结构函数

  • Dart中类结构函数写法有许多种,既能够运用与Java彻底相同的写法,也能够运用Dart特有写法,详细写入如下:

        Class TestA {
            int a = 0;
            int b = 0;
            ///与Java相同的根本写法
            TestA(int a, int b) {
                this.a = a;
                this.b = b;
            }
            ///Dart 特有结构写法,
            ///办法1:
            TestA(this.a, this.b);
            ///办法2:
            TestA(int x, int y)
                : this.a = x,
                  this.b = y;
            ///办法3:命名结构,与Kotlin中的扩展函数相似,但功用彻底不同。
            TestA.instance(this.a, this.b);
       } 
    

    个人感觉,为了便利与Java区分,不建议运用与Java相同的结构写法,而且Dart特有的结构写法,愈加简洁。

2.2 目标操作

  • 目标创立:

        ///Dart中,能够和Java相同相同,运用new关键字立异目标
        TestA a = new TestA();
        ///相同也能够运用Kotlin办法相同,创立目标
        TestA b = TestA();
        var c = TestA();
    
  • 目标属性赋值:

        ///通用赋值办法:
        TestA object = TestA();
        object.x = 10;
        object.y = 20;
        ///Dart特有赋值办法:
        TestA object = TestA()
            ..x = 10
            ..y = 20;
    

    Dart特有的赋值办法看起来有些古怪,但是多看看也就习惯了,留意分号()在赋值完毕后增加,赋值过程中不需求加。

2.3 空安全

  • Dart 中拥有与Kotlin 相同的变量空安全机制。在界说可为空的变量时,需求在变量后加 ?,示例如下:

        class Test {
            String? x = null;
            void method() {
               ///当变量可能为null时,增加问号,检查目标是否为null,不为null时,才会实施
               print(x?.length);
               ///相似Java 三元表达式,Kotlin变量判别是否为null,若为null,则赋予对应值。
               String y = x ?? 'hello word';
               ///当十分十分十分确认,变量不为null时,能够运用!,强制声明变量肯定不为null
               print(x!.length);
            }
        }
    

2.4 可变参数

  • Dart具有与Kotlin相同的可变参数的功用,仅仅完成办法有些许不同,示例如下:

        class Test() {
            ///命名参数,required修饰的参数都为必填
            void method1({required int a, required int b}) {
                print('add = ${a + b}');
            }
            ///默认参数,能够为参数赋予默认值,运用时,能够不传入该参数
            void method2({required int a, int b = 0}) {
                print('add = ${a + b}');
            }
            /// 位置参数,其特点是必须按次序依次进行指定若干入参
            void method3(int a, [int b = 1, int c = 0]) {
               print('param: a = ${a}, b = ${b}, c = ${c}');
            }
            void test() {
                method1(a: 10, b 10);
                method2(a: 10);
                method3(10);
                method3(10, 20);
                method3(10, 20, 30);
            }
        }
    

3.关键字差异

这里将从Dart与Java不同的关键字,叙述不同的关键字对功用及编码方面的影响。

3.1 可见规模关键字

  • Dart的类,办法,变量只有两种拜访类型,可拜访/不行拜访:

  • 在类名,办法名,变量名前增加 _ (下划线),即为外部类不行拜访;没有 _ (下划线)为可拜访。

  • 没有拜访规模控制关键字,public, private, protect。

        class TestB {
            ///公共变量
           int a = 10;
           ///私有变量,仅能在本类中调用
           int _b = 20;
           ///常量界说, 与Kotlin中界说相同
           const c = 30; 
           ///相当于Kotlin的 lateinit,推迟初始化变量
           late String d;
           ///公共办法,能够供内部/外部类调用
           void method1() {
           }
           ///私有办法,只能在本类调用
           void _method2() {
               var object = _TestC();
           }
           //静态办法,与Java运用办法一致,TestB.method3() 调用
           static void method3() {
           }
        }
        ///私有类,拜访规模在本.dart文件中(在TestB类中能够拜访),其他文件中无法拜访
        class _TestC {
        }
    

3.2 interface & implement 运用差异:

  • Dart中, 没有interface 接口关键字的界说,但是有implement

  • implement 关键字运用,能够完成所有类:抽象类及一般类,需求完成类中所有界说的变量及办法,如下图所示:

       implement 完成一般类:
       class BaseA {
           int x = 10;
           void method1() {
           }
       }
       class ImplementA implements BaseA {
           @override
           int x = 0;
           @override
           void method1() {
               //TODO
           }
       }
    
        implement 完成抽象类:
        abstract class BaseB {
            final int a = 0;
            void method1();
            void method2() {
            }
        }
        class ImplementB implement BaseB {
            @override
            //TODO
            int get a => 0;
            @overide
            void method1() {
                //TODO
            }
            @override
            void method2() {
                //TODO
            }
        }
    
  • 与Java & Kotlin相同,一个类能够完成多个(接口)类。

  • 接口二义性问题处理:当 C 类完成 A 、B 接口,会强制重写所有办法,成员变量供给 get 办法;即在当时类,办法只具有一种完成,变量值需从头赋值,这样就处理了二义性问题。示例如下:

        class C implement A, B {
            @override
            String str = 'hello world';
            @override
            void go() {
                //TODO
            }
        }
    

3.3 with & mixin 混入

  • 意义:with & mixin 为Dart完成混入(mixins)的关键字,混入是指将一个类的代码插入到另一个类中,以增强该类的功用,而不需求创立一个新的子类。

  • 效果:完成类功用扩展(能够一起混入多个)。比如Java & Kotlin 能够经过内部类的方式,来扩展类功用。

  • 与一般类差异:混入类,没有结构办法,无法实例化。

  • 与接口差异:接口只界说一类功用接口,没有完好功用完成;混入类需具有完好功用完成。

        ///混入类界说
        mixin Write {
            final String word = 'hello world';
            void write() {
                print('person can write: $word');
            }
        }
        ///一般类接入混入类,引进混入类完成功用
        class Person with Write {
            @override
            String get word => 'hello word! ++';
        }
        class Test {
            void method() {
                Person p = Person();
                p.write();
            }
        }
    

混入类功用与接口相似,所以相同存在二义性问题,那么混入类是怎么处理二义性问题的呢?

  • 如C 以先A ,后B次序混入两个类,A, B 中都含有一个变量名name的字符串,混入C后,打印字符串name,显现的为后混入B类中name的值。 即混入多个类时,若界说的相同类型&相同称号的变量,值为最终混入的类的值。
  • 若变量名相同,但变量类型不同,一起混入会报错。

3.4 extension 拓宽/扩展办法

  • 这个功用与Kotlin的扩展办法是相似的,都能够在不修正类文件的前提下,扩展类办法。

  • Kotlin不只能够增加扩展办法,一起能够增加扩展变量。Dart只能够增加拓宽办法。

        extension StringUtil on String {
            bool isNullorEmpty(String? str) {
                return str == null || str.isEmpty;
            }
        }
    

3.5 on 关键字。

  • on 关键字用于混入类间,完成相似 extends 的关系。即混入类能够经过 on 关键字引进其他类的功用。需求留意的是,混入类不只能够引进混入类,也能够引进一般类与抽象类。例如:

        mixin D {
            String d = 'hello word! D';
            void run() {
                print('on keyword --- ${d}')
            }
        }
        mixin E on D {
           @override
           set(String value) {
               d = value;
           }
           @override
           void run() {
               super.run();
           }
        }
    
  • onextension 合作运用,表明对哪个类进行扩展。

3.6 switch 关键字

  • switch 关键字与Java中的功用相同,即判别履行分支。其间有一个需求留意的细节,Dart中,目标类型也能够作为分支判别条件。

        class Test {
            void method1() {
                Person p1 = Person();
                Person p2 = Person();
                Person p3 = Person();
                Person p = p1;
                switch(p) {
                    case p1:
                    //TODO
                    break;
                    case p2:
                    //TODO
                    break;
                    case p3:
                    //TODO
                    break;
                }
            }
        }
    
  • Java中,判别目标只能为根本数据类型,如下图所示。

Dart 与 Java & Kotlin 差异一览

3.7 set & get 关键字

  • 与Kotlin相似,Dart供给了 set & get关键字,完成变量的 setter & getter 功用。示例如下:

        class Test {
            void method() {
                A a = A();
                print(' get value : ${a.getValue}');
                a.setValue(10);
                print(' get value : ${a.getValue}');
            }
        }
        class A {
            int _value = 0;
            int get getValue => _value;
            /// => 是Dart中的省掉写法,完好办法如下:
            int get getValue {
                return _value;
            }
            set setValue(int value) {
                _value = value;
            }
        }
    

3.8 Function 函数目标

  • 界说:函数目标与Kotlin的高阶函数相似,能够理解为函数目标类型的关键字;指定传入参数,履行对应代码块后,回来指定类型的回来值。这也是Dart 比 Java 更接近万物皆目标的体现。

  • 效果:与Kotlin的高阶函数功用一致,界说一类功用的完成规则。示例如下:

        typedef Operate = int Function(int, int);
        class Test {
            void method() {
                Operate add = (a, b) {
                    return a + b;
                }
                add.call(10, 20)
            }
        }
    

总结

总的来说,Dart言语与Java&Kotlin许多相似的当地,在最开始学习时,记住不同点,编码方面就不会有太多的阻止。但是从言语规划层面看,Dart与Java&Kotlin还是有很大的差异,等我悟道之后,再和大家细说。 如果有需求完善,或者不认同的当地,欢迎大家留言评论。

本文正在参与「金石方案」