类
类定义
dart
class Point {
num x;
num y;
Point(this.x, this.y);
// Named constructor
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}
var jsonData = JSON.decode('{"x":1, "y":2}');
// 使用 new 关键字 来创建新的对象
// Create a Point using Point().
var p1 = new Point(2, 2);
// 使用 构造函数 来创建新的对象
// Create a Point using Point.fromJson().
var p2 = new Point.fromJson(jsonData);
// 使用点(.)来引用对象的变量或者方法:
var p = new Point(2, 2);
// Set the value of the instance variable y.
p.y = 3;
// Get the value of y.
assert(p.y == 3);
// Invoke distanceTo() on p.
num distance = p.distanceTo(new Point(4, 4));
// 使用 ?. 来替代 . 可以避免当左边对象为 null 时候 抛出异常:
// If p is non-null, set its y value to 4.
p?.y = 4;
// 使用常量构造函数 可以创建编译时常量,
// 要使用常量构造函数只需要用 const 替代 new 即可:
var p = const ImmutablePoint(2, 2);
// 两个一样的编译时常量其实是 同一个对象:
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
// 可以使用 Object 的 runtimeType 属性来判断实例 的类型,
// 该属性 返回一个 Type 对象。
print('The type of a is ${a.runtimeType}');
go
js
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
typeof Point // "function"
Point === Point.prototype.constructor // true
python
类提供了一种组合数据和功能的方法。 创建一个新类意味着创建一个新 类型 的对象, 从而允许创建一个该类型的新 实例 。 每个类的实例可以拥有保存自己状态的属性。
多个名称(在多个作用域内)可以绑定到同一个对象。 这在其他语言中称为别名。
namespace 是一个从名字到对象的映射。 大部分命名空间当前都由 Python 字典实现, 从某种意义上说,对象的属性集合也是一种命名空间的形式。 不同命名空间中的名称之间绝对没有关系;
我把任何跟在一个点号之后的名称都称为 属性
模块属性是可以写,你可以写出 modname.the_answer = 42 。 可写的属性同样可以用 del 语句删除。
内置名称实际上也存在于一个模块中;这个模块称作 builtins
# 作用域和命名空间示例
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
# After local assignment: test spam
# After nonlocal assignment: nonlocal spam
# After global assignment: nonlocal spam
# In global scope: global spam
# MyClass.i 和 MyClass.f 就是有效的属性引用,
# 将分别返回一个整数和一个函数对象。
# 类属性也可以被赋值,因此可以通过赋值来更改 MyClass.i 的值。
class MyClass:
"""A simple example class"""
i = 12345
# 当一个类定义了 __init__() 方法时,
# 类的实例化操作会自动为新创建的类实例发起调用 __init__()
def __init__(self):
self.data = []
def f(self):
return 'hello world'
x = MyClass()
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5) # 实例化
构造函数
Constructors
dart
定义一个和类名字一样的方法就定义了一个构造函数
class Point {
num x;
num y;
Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
// 由于把构造函数参数赋值给实例变量的场景太常见了,
// Dart 提供了一个语法糖来简化这个操作:
class Point {
num x;
num y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
go
js
python
class MyClass:
def __init__(self):
pass
默认构造函数
dart
如果你没有定义构造函数,则会有个默认构造函数。 默认构造函数没有参数,并且会调用超类的 没有参数的构造函数。
go
js
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。 一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
python
命名构造函数
dart
构造函数不能继承,所以超类的命名构造函数 也不会被继承。 如果你希望 子类也有超类一样的命名构造函数, 你必须在子类中自己实现该构造函数。
class Point {
num x;
num y;
Point(this.x, this.y);
// Named constructor
Point.fromJson(Map json) {
x = json['x'];
y = json['y'];
}
}
go
js
python
调用超类构造函数
dart
- 默认情况下,子类的构造函数会自动调用超类的 无名无参数的默认构造函数。 超类的构造函数在子类构造函数体开始执行的位置调用。
- 如果提供了一个 initializer list(初始化参数列表) , 则初始化参数列表在超类构造函数执行之前执行。
- 如果在构造函数的初始化列表中使用 super(),需要把它放到最后。
构造函数执行顺序:
- initializer list(初始化参数列表)
- superclass’s no-arg constructor(超类的无名无参构造函数)
- main class’s no-arg constructor(主类的无名无参构造函数)
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
// 此处实现超类的命名构造函数
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
go
js
python
初始化列表
dart
在构造函数体执行之前除了可以调用超类构造函数之外, 还可以 初始化实例参数。 使用逗号分隔初始化表达式。 初始化表达式等号右边的部分不能访问 this。
class Point {
num x;
num y;
Point(this.x, this.y);
// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map jsonMap)
: x = jsonMap['x'],
y = jsonMap['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}
// 初始化列表非常适合用来设置 final 变量的值
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
main() {
var p = new Point(2, 3);
print(p.distanceFromOrigin);
}
go
js
python
重定向构造函数
dart
有时候一个构造函数会调动类中的其他构造函数。 一个重定向构造函数是没有代码的, 在构造函数声明后,使用 冒号调用其他构造函数。
class Point {
num x;
num y;
// The main constructor for this class.
Point(this.x, this.y);
// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}
go
js
python
常量构造函数
dart
如果你的类提供一个状态不变的对象,你可以把这些对象 定义为编译时常量。 要实现这个功能,需要定义一个 const 构造函数, 并且声明所有类的变量为 final。
class ImmutablePoint {
final num x;
final num y;
const ImmutablePoint(this.x, this.y);
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
}
go
js
python
工厂方法构造函数
dart
- 如果一个构造函数并不总是返回一个新的对象,则使用 factory 来定义 这个构造函数。 例如,一个工厂构造函数 可能从缓存中获取一个实例并返回,或者 返回一个子类型的实例。
- 工厂构造函数无法访问 this。
// 下面代码演示工厂构造函数 如何从缓存中返回对象。
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to the _ in front
// of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) {
print(msg);
}
}
}
// 使用 new 关键字来调用工厂构造函数。
var logger = new Logger('UI');
logger.log('Button clicked');
go
js
python
实例变量和方法
实例变量
Instance variables 实例变量
dart
// 每个实例变量都会自动生成一个 getter 方法(隐含的)。
// Non-final 实例变量还会自动生成一个 setter 方法。
class Point {
num x; // Declare instance variable x, initially null.
num y; // Declare y, initially null.
num z = 0; // Declare z, initially 0.
}
main() {
var point = new Point();
point.x = 4; // Use the setter method for x.
assert(point.x == 4); // Use the getter method for x.
assert(point.y == null); // Values default to null.
}
go
js
class IncreasingCounter {
constructor() {
this._count = 0;
}
get value() {
console.log('Getting the current value!');
return this._count;
}
increment() {
this._count++;
}
}
class IncreasingCounter {
_count = 0;
get value() {
console.log('Getting the current value!');
return this._count;
}
increment() {
this._count++;
}
}
class foo {
bar = 'hello';
baz = 'world';
constructor() {
// ...
}
}
class Duck {
constructor(name) {
this.name = name
}
fly() {
console.log(`${this.name} can fly`)
}
// not static: call a method on an instance
// const duck = new Duck(...)
// duck.create(...)
//
// static: call a method on a class
// Duck.create(...)
static create(name, kind) {
if (kind === 'mallard') {
return new MallardDuck(name)
} else if (kind === 'rubber') {
return new RubberDuck(name)
} else {
// this = Duck
return new this(name)
}
}
}
class MallardDuck extends Duck {
// get:
// use duck.color instead of duck.color()
get color() {
return 'green'
}
}
class RubberDuck extends Duck {
constructor(name, eyeColor = 'black') {
super(name)
this.eyeColor = eyeColor
}
fly() {
super.fly()
console.log(`Just kidding, ${this.name} cannot fly`)
}
get color() {
return 'yellow'
}
}
const regularDuck = new Duck('reggie')
// reggie can fly
regularDuck.fly()
const mallardDuck = Duck.create('mal', 'mallard')
// mal
console.log(mallardDuck.name)
// green
console.log(mallardDuck.color)
rubberDuck = new RubberDuck('vic', 'blue')
// vic can fly
// Just kidding, vic cannot fly
rubberDuck.fly()
// yellow
console.log(rubberDuck.color)
// blue
console.log(rubberDuck.eyeColor)
python
有两种有效的属性名称,数据属性和方法。 数据属性 对应于 Smalltalk 中的“实例变量”,以及 C++ 中的“数据成员”。 另一类实例属性引用称为 方法。 方法是“从属于”对象的函数。 但是 x.f 与 MyClass.f 并不是一回事 --- 它是一个 方法对象,不是函数对象
数据属性会覆盖掉具有相同名称的方法属性; 为了避免会在大型程序中导致难以发现的错误的意外名称冲突, 明智的做法是使用某种约定来最小化冲突的发生几率。 可能的约定包括方法名称使用大写字母, 属性名称加上独特的短字符串前缀(或许只加一个下划线), 或者是用动词来命名方法,而用名词来命名数据属性
方法的第一个参数常常被命名为 self。 这也不过就是一个约定: self 这一名称在 Python 中绝对没有特殊含义。
class Duck:
def __init__(self, name):
self.name = name
def fly(self):
print(f"{self.name} can fly")
# not @classmethod: call a method on an instance
# duck = Duck(...)
# duck.create(...)
#
# @classmethod: call a method on a class
# Duck.create(...)
@classmethod
def create(cls, name, kind):
if kind == "mallard":
return MallardDuck(name)
elif kind == "rubber":
return RubberDuck(name)
else:
# cls = Duck
return cls(name)
class MallardDuck(Duck):
# @property:
# use duck.color instead of duck.color()
@property
def color(self):
return "green"
class RubberDuck(Duck):
def __init__(self, name, eye_color="black"):
super().__init__(name)
self.eye_color = eye_color
def fly(self):
super().fly()
print(f"Just kidding, {self.name} cannot fly")
@property
def color(self):
return "yellow"
regularDuck = Duck("reggie")
# reggie can fly
regularDuck.fly()
mallardDuck = Duck.create("mal", "mallard")
# mal
print(mallardDuck.name)
# green
print(mallardDuck.color)
rubberDuck = RubberDuck("vic", "blue")
# vic can fly
# Just kidding, vic cannot fly
rubberDuck.fly()
# yellow
print(rubberDuck.color)
# blue
print(rubberDuck.eye_color)
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
# 以下代码中的 tricks 列表不应该被用作类变量,
# 因为所有的 Dog 实例将只共享一个单独的列表:
class Dog:
tricks = [] # mistaken use of a class variable
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks # unexpectedly shared by all dogs
['roll over', 'play dead']
# 正确的类设计应该使用实例变量:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = [] # creates a new empty list for each dog
def add_trick(self, trick):
self.tricks.append(trick)
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
实例方法
Instance methods(实例函数)
dart
对象的实例函数可以访问 this。
import 'dart:math';
class Point {
num x;
num y;
Point(this.x, this.y);
num distanceTo(Point other) {
var dx = x - other.x;
var dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
}
go
js
python
get和set
Getters and setters
dart
- Getters 和 setters 是用来设置和访问对象属性的特殊 函数。 每个实例变量都隐含的具有一个 getter, 如果变量不是 final 的则还有一个 setter。
- 通过实行 getter 和 setter 来创建新的属性, 使用 get 和 set 关键字定义 getter 和 setter
class Rectangle {
num left;
num top;
num width;
num height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and bottom.
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
main() {
var rect = new Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
go
js
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'getter'
python
类变量和方法
静态变量
Static variables(静态变量)
dart
静态变量在第一次使用的时候才被初始化
class Color {
static const red = const Color('red'); // A constant static variable.
final String name; // An instance variable.
const Color(this.name); // A constant constructor.
}
main() {
assert(Color.red.name == 'red');
}
go
js
python
静态方法
Static methods(静态函数)
dart
- 静态函数不再类实例上执行, 所以无法访问 this。
- 对于通用的或者经常使用的静态函数,考虑 使用顶级方法而不是静态函数。
- 静态函数还可以当做编译时常量使用。
import 'dart:math';
class Point {
num x;
num y;
Point(this.x, this.y);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
main() {
var a = new Point(2, 2);
var b = new Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(distance < 2.9 && distance > 2.8);
}
go
js
python
抽象及继承
抽象类
Abstract classes(抽象类)
dart
使用 abstract
修饰符定义一个 抽象类—一个不能被实例化的类。
抽象类通常用来定义接口, 以及部分实现。 如果你希望你的抽象类
是可实例化的,则定义一个 工厂 构造函数。
// 抽象类通常具有 抽象函数。 下面是定义具有抽象函数的 抽象类的示例:
// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
// ...Define constructors, fields, methods...
void updateChildren(); // Abstract method.
}
// 下面的类不是抽象的,但是定义了一个抽象函数,这样 的类是可以被实例化的:
class SpecializedContainer extends AbstractContainer {
// ...Define more constructors, fields, methods...
void updateChildren() {
// ...Implement updateChildren()...
}
// Abstract method causes a warning but
// doesn't prevent instantiation.
void doSomething();
}
go
js
python
抽象函数
Abstract methods(抽象函数)
dart
- 实例函数、 getter、和 setter 函数可以为抽象函数,
- 抽象函数是只定义函数接口但是没有实现的函数,由子类来 实现该函数。
- 如果用分号来替代函数体则这个函数就是抽象函数。
- 调用一个没实现的抽象函数会导致运行时异常。
abstract class Doer {
// ...Define instance variables and methods...
void doSomething(); // Define an abstract method.
}
class EffectiveDoer extends Doer {
void doSomething() {
// ...Provide an implementation, so the method is not abstract here...
}
}
go
js
python
隐式接口
Implicit interfaces(隐式接口)
dart
每个类都隐式的定义了一个包含所有实例成员的接口, 并且这个类实现了这个接口。 一个类可以通过 implements 关键字来实现一个或者多个接口, 并实现每个接口定义的 API。
Dart提供了隐式接口的功能,在定义类时使用implements关键字, 可以像extends一样从父类获取到成员, 与extends不同的是,这不是继承,而是接口成员约束.
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Imposter implements Person {
// We have to define this, but we don't use it.
final _name = "";
String greet(who) => 'Hi $who. Do you know who I am?';
}
greetBob(Person person) => person.greet('bob');
main() {
print(greetBob(new Person('kathy')));
print(greetBob(new Imposter()));
}
// 下面是实现多个接口 的示例:
class Point implements Comparable, Location {
// ...
}
go
js
python
继承
Extending a class(扩展类)继承
dart
使用 extends 定义子类, supper 引用 超类: 子类可以覆写实例函数,getter 和 setter。
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
// ...
}
class SmartTelevision extends Television {
void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();
}
// ...
}
// 如果调用了对象上不存在的函数,则就会触发 noSuchMethod() 函 数。
class A {
// Unless you override noSuchMethod, using a
// non-existent member results in a NoSuchMethodError.
void noSuchMethod(Invocation mirror) {
print('You tried to use a non-existent member:' +
'${mirror.memberName}');
}
}
// 还可以使用 @override 注解来 表明你的函数是想覆写超类的一个函数:
class A {
@override
void noSuchMethod(Invocation mirror) {
// ...
}
}
// 如果你使用 noSuchMethod() 函数来实现每个可能的 getter 、setter、 以及其他类型的函数,
// 你可以使用 @proxy 注解来避免警告信息:
@proxy
class A {
void noSuchMethod(Invocation mirror) {
// ...
}
}
// 如果你知道编译时的具体类型,则可以 实现这些类来避免警告,和 使用 @proxy 效果一样:
class A implements SomeClass, SomeOtherClass {
void noSuchMethod(Invocation mirror) {
// ...
}
}
go
js
python
class DerivedClassName(BaseClassName):
pass
class DerivedClassName(modname.BaseClassName):
多重继承
混入
Adding features to a class: mixins(为类添加新的功能)
dart
Mixins 是一种在多类继承中重用 一个类代码的方法。 使用 with 关键字后面为一个或者多个 mixin 名字来使用 mixin。
class Musician extends Performer with Musical {
// ...
}
class Maestro extends Person with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
// 定义一个类继承 Object,该类没有构造函数,
// 不能调用 super ,则该类就是一个 mixin。
// 注意: 从 Dart 1.13 开始, 这两个限制在 Dart VM 上 没有那么严格了:
// 1.Mixins 可以继承其他类,不再限制为继承 Object
// 2.Mixins 可以调用 super()。
abstract class Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
go
js
python
class DerivedClassName(Base1, Base2, Base3):
pass
可覆写的操作符
Overridable operators(可覆写的操作符)
dart
下表中的操作符可以被覆写。
< + | []
> / ^ []=
<= ~/ & ~
>= * << ==
– % >>
- 例如,如果你定义了一个 Vector 类,你可以定义一个 + 函数来实现两个向量相加。
- 如果你覆写了 == ,则还应该覆写对象的 hashCode getter 函数。
class Vector {
final int x;
final int y;
const Vector(this.x, this.y);
/// Overrides + (a + b).
Vector operator +(Vector v) {
return new Vector(x + v.x, y + v.y);
}
/// Overrides - (a - b).
Vector operator -(Vector v) {
return new Vector(x - v.x, y - v.y);
}
}
main() {
final v = new Vector(2, 3);
final w = new Vector(2, 2);
// v == (2, 3)
assert(v.x == 2 && v.y == 3);
// v + w == (4, 5)
assert((v + w).x == 4 && (v + w).y == 5);
// v - w == (0, 1)
assert((v - w).x == 0 && (v - w).y == 1);
}
go
js
python
枚举类型
Enumerated types(枚举类型)
dart
枚举类型通常称之为 enumerations 或者 enums, 是一种特殊的类,用来表现一个固定 数目的常量。
- 无法继承枚举类型、无法使用 mixin、无法实现一个枚举类型
- 无法显式的初始化一个枚举类型
// 使用 enum 关键字来定义枚举类型:
enum Color {
red,
green,
blue
}
// 枚举类型中的每个值都有一个 index getter 函数,
// 该函数返回该值在枚举类型定义中的位置(从 0 开始)。
assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);
// 枚举的 values 常量可以返回 所有的枚举值。
List<Color> colors = Color.values;
assert(colors[2] == Color.blue);
// 可以在 switch 语句 中使用枚举
enum Color {
red,
green,
blue
}
// ...
Color aColor = Color.blue;
switch (aColor) {
case Color.red:
print('Red as roses!');
break;
case Color.green:
print('Green as grass!');
break;
default: // Without this, you see a WARNING.
print(aColor); // 'Color.blue'
}
go
Go里面有一个关键字iota,这个关键字用来声明enum的时候采用, 它默认开始值是0,const中每增加一行加1:
package main
import (
"fmt"
)
const (
x = iota // x == 0
y = iota // y == 1
z = iota // z == 2
w // 常量声明省略值时,默认和之前一个值的字面相同。这里隐式地说w = iota,因此w == 3。
// 其实上面y和z可同样不用"= iota"
)
const v = iota // 每遇到一个const关键字,iota就会重置,此时v == 0
const (
h, i, j = iota, iota, iota //h=0,i=0,j=0 iota在同一行值相同
)
const (
a = iota //a=0
b = "B"
c = iota //c=2
d, e, f = iota, iota, iota //d=3,e=3,f=3
g = iota //g = 4
)
func main() {
fmt.Println(a, b, c, d, e, f, g, h, i, j, x, y, z, w, v)
}
js
python
可调用的类
Callable classes(可调用的类)
dart
如果 Dart 类实现了 call() 函数则 可以当做方法来调用。
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');
}
go
js
python
自定义hash码
Implementing map keys 自定义 hash 码
dart
Dart 中的每个对象都有一个整数 hash 码,这样每个对象都 可以当做 map 的 key 来用。 但是,你可以覆写 hashCode getter 来自定义 hash 码的实现, 如果你这样做了,你也需要 同时覆写 == 操作符。 相等的对象(使用 == 比较)的 hash 码应该一样。 Hasm 码并不要求是唯一的, 但是应该具有良好的分布形态。
class Person {
final String firstName, lastName;
Person(this.firstName, this.lastName);
// Override hashCode using strategy from Effective Java,
// Chapter 11.
int get hashCode {
int result = 17;
result = 37 * result + firstName.hashCode;
result = 37 * result + lastName.hashCode;
return result;
}
// You should generally implement operator == if you
// override hashCode.
bool operator ==(other) {
if (other is! Person) return false;
Person person = other;
return (person.firstName == firstName &&
person.lastName == lastName);
}
}
main() {
var p1 = new Person('bob', 'smith');
var p2 = new Person('bob', 'smith');
var p3 = 'not a person';
assert(p1.hashCode == p2.hashCode);
assert(p1 == p2);
assert(p1 != p3);
}
go
js
python
可迭代对象
Iteration 可迭代对象
dart
Iterable 和 Iterator 类支持 for-in 循环。 当你创建一个类的时候,继承或者实现 Iterable 可以 提供一个用于 for-in 循环的 Iterators。 实现 Iterator 来定义实际的遍历操作。
class Process {
// Represents a process...
}
class ProcessIterator implements Iterator<Process> {
Process current;
bool moveNext() {
return false;
}
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of Iterable.
class Processes extends IterableBase<Process> {
final Iterator<Process> iterator =
new ProcessIterator();
}
main() {
// Iterable objects can be used with for-in.
for (var process in new Processes()) {
// Do something with the process.
}
}
go
js
python
定义一个 __iter__()
方法来返回一个带有
__next__()
方法的对象。 如果类已定义了
next(),则 iter() 可以简单地返回 self:
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
Typedefs
dart
在 Dart 语言中,方法也是对象。
typedef int Compare(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
main() {
SortedCollection coll = new SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
// 由于 typedefs 只是别名,他们还提供了一种 判断任意 function 的类型的方法
typedef int Compare(int a, int b);
int sort(int a, int b) => a - b;
main() {
assert(sort is Compare); // True!
}
go
js
python