美文网首页Flutter
03 - Dart笔记-面向对象

03 - Dart笔记-面向对象

作者: 云佾风徽 | 来源:发表于2019-01-22 00:05 被阅读0次

新公司迭代需求有点猛,拖了很长时间。
计划Dart还有一篇高级特性的笔记

[TOC]

类的使用

通过构造函数实例化

// 非 命名构造函数
var test = Test();
  
// 命名构造函数(named ctor)
var testFeature = TestFeature.fromTest(test);
// 常量构造函数
var constObj1 = const TestConstCtor(1);

常量构造函数

  • const构造函数必须用于成员变量都是final的类
  • 构建常量实例必须使用定义的常量构造函数,如果不是常量构造函数是无法在实例化时使用const修饰符
  • 如果实例化时不加const修饰符,即使调用的是声明为const的构造函数,实例化的也不是常量实例
class TestConstCtor {
  final int x;
  // const构造函数必须用于成员变量都是final的类
  // Can't define a constructor for a class with non-final fields
//  String y;
  const TestConstCtor(this.x);
}

void testConstCtor() {

  // 构建常量实例必须使用定义的常量构造函数,如果不是常量构造函数是无法在实例化时使用const修饰符
  // The constructor being called isn't a const constructor
  //  var test2 = const Test();
  var constObj1 = const TestConstCtor(1);
  var constObj2 = const TestConstCtor(2);
  var constObj2_2 = const TestConstCtor(2);
  // 如果实例化时不加const修饰符,即使调用的是声明为const的构造函数,实例化的也不是常量实例
  var constObj2_3 = TestConstCtor(2);

  print("const TestConstCtor(1) and const TestConstCtor(2) same: ${identical
    (constObj1, constObj2)}"); //false

  print("const TestConstCtor(2) and const TestConstCtor(2) same: ${identical
    (constObj2_2, constObj2)}");//true

  print("TestConstCtor(2) and const TestConstCtor(2) same: ${identical
    (constObj2_2,constObj2_3)}");//false
}

对象的运行时类型

obj.runtimeType返回的是对象的实际类型,即使根据多态的特性将变量声明为父类类型,runtimeType也会返回实际类型

setter/getter

  • 类的成员变量默认生成与字段同名的set/get函数

  • 字面意义上的私有成员变量也会生成set/get函数,在类的外部可以调用

    class TestFeature {
      int c;
      int d;
    
      int _f;
      // ...
    }
    
    test(){
        var testFeature = TestFeature.fromTest(test);
        testFeature._f = 20;
        print("_f = ${testFeature._f}");
    }
    

  • 计算属性的set/get

    <type> get <computedProperty> {
        
    }
    set <computedProperty>(<type> value) {
        
    }
    

构造函数

警告:初始化器的右边部分中无法访问this关键字。

默认构造函数

  • 不声明构造函数则提供默认构造函数
  • 只要有构造函数,即使是命名构造函数,就不会提供默认的构造函数
  • 无参数,非命名
void testDef() {
  // 只要有构造函数,即使是命名构造函数,就不会提供默认的构造函数
  // The class 'TestDefault' doesn't have a default constructor
//  var testDefault = TestDefault();
}

class TestDefault {
  int a;
  int b;

//  TestDefault();
  TestDefault.namedCtor(int c) {
    a = c;
    b = c;
  }
}

带参数的非命名构造函数

  • 直接给类成员变量赋值的语法糖

    class Test {
        int a;
        Test(this.a);
    }
    
  • 构造函数的参数列表与普通函数相同,可以处理无参,必须参数和可选参数等不同的情况

    class TestNotNamed {
      int c;
      int d;
      int e;
      int f;
      
    //  TestNotNamed();
    //  TestNotNamed(this.d);
    //  TestNotNamed(this.c, {this.d, this.e, this.f});
    //  TestNotNamed(this.c, [this.d, this.e, this.f]);
    
      TestNotNamed(int x, int y) {
        c = x + y;
      }
    
    }
    

命名的构造函数

使用命名构造函数可以在一个类中定义多个构造函数,不同的命名构造函数可以专门用于不同的场景:

class Point {
  num x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}

构造函数没有继承

  • 子类不从父类继承构造函数。
  • 如果父类有默认构造函数,则子类任意定义构造函数,默认会调用执行父类的默认构造函数,不必强制使用初始化器列表调用父类的构造函数
  • 父类没有提供默认构造函数,子类须要显示指定使用父类的哪一个构造函数,并传递参数
class TestParent {
  int m;

  TestParent.noArg();
}

class TestChild extends TestParent {
  int x;

  // 不显示定义构造函数则报错
//  TestChild() :super.noArg();
  TestChild.noArg() : super.noArg();
}

构造函数的初始化器

初始化器在构造函数声明和方法体中间。

构造函数向初始化器传递参数

不需要使用this区分入参和类的成员变量

Square(int id, int width, int height)
      : super(id, width: width, height: height);

Square.bySize(int id, int size) : super(id, width: size, height: size);

super调用父类构造函数

  • 父类构造函数初始化器必须是初始化器列表的最后一项
Square(int id, int width, int height)
    : super(id, width: width, height: height);

Square.testInitList(int id)
      : desc = "it's a desc",
        // 重定向构造函数初始化器必须单独使用,不能和域初始化器和父类构造函数初始化器同时使用
        // The redirecting constructor can't have a field initializer
//        this.bySize(id,10),
        super(id)
  // 父类构造函数初始化器必须是初始化器列表的最后一项
  // super call must be last in initializer list
//      ,comment = "a new comment"
  ;

this重定向构造函数

  • 重定向构造函数初始化器必须单独使用,不能和域初始化器和父类构造函数初始化器同时使用
  Rectangle.twiceWidth(int id, int width)
      // 构造函数重定向
      // 初始化器不能使用this,也就是只能使用顶层函数和static静态函数
      : this(id, width: width, height: getTwiceWidth(width));

Square.testInitList(int id)
      : desc = "it's a desc",
        // 重定向构造函数初始化器必须单独使用,不能和域初始化器和父类构造函数初始化器同时使用
        // The redirecting constructor can't have a field initializer
//        this.bySize(id,10)

初始化实例变量

class Square extends Rectangle {
    String comment;
    // ...
    Square.initMember()
      :comment="a comment",
        super(1);
}

工厂构造函数

  • 构造函数前使用factory关键字标识其是工厂构造函数
  • factory 声明的工厂构造函数不能使用this关键字,这种构造函数类似static静态函数
class TestFactory {
  final String factoryName;

  static final Map<String, TestFactory> _cache = <String, TestFactory>{};

  TestFactory._internal(this.factoryName);

  // factory 声明的工厂构造函数不能使用this关键字,这种构造函数类似static静态函数
  // Initializing formal parameters can't be used in factory constructors.
//  factory TestFactory(this.factoryName);

  factory TestFactory(String factoryName) {
    var instance = _cache[factoryName];
    if (null == instance) {
      instance = TestFactory._internal(factoryName);
      _cache[factoryName] = instance;
      return instance;
    } else {
      return instance;
    }
  }

}

类的特性

类的实例方法/set/get/计算属性

  • set/get默认实现,不需要显式声明和实现

  • 如果需要处理set/get,按照特定格式声明set/get

    <type> get <property> {
        
    }
    
    // 显式定义setter时避免设置返回类型
    // avoid return type on setters
    /*void*/ set <property>(<params>) {
        
    }
    
  • 可以通过set/get设置计算属性。但是与Vue不同,调用计算属性的get仍然每次都会执行计算

    class TestMethod {
      int a;
      int b;
      int c;
      int d;
    
      TestMethod(this.a, this.b, this.c, this.d);
    
      int get e {
        // 计算属性在执行getter方法时每次都会执行statement,与Vue的计算属性不同
        print("get e");
        int ret = a + b;
        return ret;
      }
    
      // 显式定义setter时避免设置返回类型
      // avoid return type on setters
      /*void*/
      set e(int vi) {
        a = vi - b;
      }
    }
    

抽象类与抽象方法、隐式接口

  • 抽象类不能(用new)实例化
  • 每个类都提供一个同名的,包含所有方法的隐式接口
  • 接口类的声明使用abstract class XXX
  • set/get 也可以声明为abstract交由子类具体实现
abstract class TestAbstract {
  void methodA() => print("real method");

  void abstractMethod(String text);

  int a;

  int get abstractGet;

  set abstractSet(int value);
}

class TestAbstractImpl extends TestAbstract {
  @override
  // TODO: implement abstractGet
  int get abstractGet => null;

  @override
  void abstractMethod(String text) {
    // TODO: implement abstractMethod
  }

  @override
  void set abstractSet(int value) {
    // TODO: implement abstractSet
  }

//  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class TestInterface {
  void saySth(String text) {
    print(text);
  }
}

class TestInterfaceImpl implements TestInterface {
  @override
  void saySth(String text) {
    // TODO: implement saySth
  }
}

操作符override

  • 函数名为操作符,函数名前使用operator标识 <returnType> operator <op>(<params>) {}
  • 支持的操作符
< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
- % >>
class TestOverrideOperator {
  int a;
  int b;

  TestOverrideOperator(this.a, this.b);

  TestOverrideOperator operator +(TestOverrideOperator opVal) =>
      TestOverrideOperator(this.a + opVal.a, this.b + opVal.b);

  @override
  String toString() {
    return 'TestOverrideOperator{a: $a, b: $b}';
  }
}

noSuchMethod

重写noSuchMethod()方法来处理程序访问一个不存在的方法或者成员变量

class Foo {
  void sayHi() => print("hi");

  int get money => 123;
}

class TestNoSuchMethod implements Foo {
  void hello() => print("hello");

  int get salary => 777;

  @override
  noSuchMethod(Invocation invocation) {
    var runtimeType = invocation.runtimeType;
    // invocation.memberName 返回的是Symbol对象,
    // #操作符 用于引用一个操作符(方法名)
    if (invocation.memberName == #sayHi) {
      if (invocation.isMethod) {
        return hello();
      }
    } else if (invocation.memberName == #money) {
      if (invocation.isGetter) {
        // 如果调用的是get/set方法,应当返回一个get/set方法的返回值
//        return hello;
        return salary;
      }
    }
    return super.noSuchMethod(invocation);
  }
}

mixin多继承

  • 子类使用with标识符声明其他继承
  • Mixin类必须是Object的直接子类
  • Mixin类不能声明构造函数
  • Mixin类中不能出现super语句
class TestMixin extends Parent with MixinA {
  String b;
}

class Parent {
  int a;
}

class MixinA {
  int c;

//  MixinA(this.c);

  void play(String text) {
    print(text);
//    super.toString();
  }
}

枚举

  • 枚举的values下标从0开始
  • <type>.values返回所有的枚举值
  • enum 使用switch必须把所有枚举都列出,否则报错
void testEnum() {
  // 获取所有的枚举值
  var values = TestEum.values;
  // 枚举的values下标从0开始
  var index2 = TestEum.TypeTwo.index;
  print("values:${values};index2:${index2}");

  var type = TestEum.TypeThree;

  // enum 使用switch必须把所有枚举都列出,否则报错
  switch (type) {
    case TestEum.TypeOne:
      break;
    case TestEum.TypeTwo:
      break;
    case TestEum.TypeThree:
      break;
  }
}

enum TestEum { TypeOne, TypeTwo, TypeThree }

泛型

  • 与java写法类似,可以在类上和方法上使用泛型
  • 运行时不会泛型擦除
  • 泛型标记不能实例化
void testGenericClass() {
  TestGeneric<MyImplA>(MyImplA(3, 5)).printDataName();
  TestGeneric<MyImplB>(MyImplB(41, 8)).printDataName();
}

class TestGeneric<T extends MyInterface> {
  final T data;

  TestGeneric(this.data);

  void printDataName() {
    print("for ${T}:name=${data.getName()}");
  }

// 泛型S不能实例化
//  S newInstance<S extends String>(String message) {
//    return new S(message);
//  }
}

abstract class MyInterface {
  String getName();
}

class MyImplA implements MyInterface {
  int a;
  int b;

  MyImplA(this.a, this.b);

  @override
  String getName() {
    return (a + b).toString();
  }
}

class MyImplB implements MyInterface {
  int c;
  int d;

  MyImplB(this.c, this.d);

  @override
  String getName() {
    return (c * d).toString();
  }
}

相关文章

  • 03 - Dart笔记-面向对象

    新公司迭代需求有点猛,拖了很长时间。计划Dart还有一篇高级特性的笔记 [TOC] 类的使用 通过构造函数实例化 ...

  • 2019-09-20: 九: Flutter之Dart第六节(类

    九: Flutter之Dart第六节(类和对象)? Dart 是一个面向对象的语言、面向对象中非常重要的概念就是类...

  • Flutter(六) Dart语言基础-面向对象特性

    Dart是一个面向对象的语言,面向对象中非常重要的概念就是类,类产生了对象。今天,我们就具体来学习Dart 中重要...

  • Dart语法 -- [06 - 类和对象]

    Dart是一个面向对象的语言,面向对象中非常重要的概念就是类,类产生了对象。 1.1. 类的定义 在Dart中,定...

  • 基础学习

    1.第一个世界级程序 Dart面向对象编程 Dart是一种面向对象的语言。面向对象是一种遵循真实世界建模的软件开发...

  • Dart语言(三)Functions(方法)

    Dart语言(三)Functions(方法) Dart是一个真正的面向对象的语言,方法本身也是个对象,这个对象类型...

  • (六)Dart Classes(类)、Constructors(

    一、Object(对象) Dart 是一个面向对象编程语言。 Dart支持基于 mixin 的继承机制(多继承)。...

  • Flutter 代码规范整理

    Dart 语法简介 Flutter是使用Dart语言开发的。Dart语言是基于类的纯面向对象语言。Dart 中的所...

  • Dart学习笔记——面向对象(一)

    面向对象编程(OOP)的三个基本特征是:封装、继承、多态 封装:封装是对象和类概念的主要特性。封装,把客观事物封装...

  • Dart学习笔记——面向对象(二)

    继承 简单继承 Dart中的类的继承: 子类使用extends关键词来继承父类。 子类会继承父类里面可见的属性和方...

网友评论

    本文标题:03 - Dart笔记-面向对象

    本文链接:https://www.haomeiwen.com/subject/agskjqtx.html