Flutter

03 - Dart笔记-面向对象

2019-01-22  本文已影响0人  云佾风徽

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

[TOC]

类的使用

通过构造函数实例化

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

常量构造函数

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

构造函数

警告:初始化器的右边部分中无法访问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 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);
}

工厂构造函数

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/计算属性

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

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

< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
- % >>
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多继承

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();
  }
}

枚举

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 }

泛型

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();
  }
}

上一篇下一篇

猜你喜欢

热点阅读