# [Class](https://dart.dev/language/classes)
* [Constructors](https://hackmd.io/@asdf121472/BJYsz1XG1g)
* [Method](https://hackmd.io/@asdf121472/B14ZHRoMkx)
* [extends 繼承](https://hackmd.io/@asdf121472/SJzdoOLXye)
* [Mixin](https://hackmd.io/@asdf121472/r1y4xx_7Jl)
* [implements](https://hackmd.io/@asdf121472/B16aZfDEJe)
* [Extension methods](https://hackmd.io/@asdf121472/Hk8fumlEyx)
* [Extension types](https://hackmd.io/@asdf121472/HJdwp-Q4kg)
* [Enums](https://hackmd.io/@asdf121472/HySzeKlG0)
* [Callable objects](https://hackmd.io/@asdf121472/HJ5BN2PV1g)
* [Class modifiers](https://hackmd.io/@asdf121472/rJnfLO9Xyx)
---
參考資料:
[1](https://ithelp.ithome.com.tw/m/articles/10265921)
---
### dart是單一繼承, 配合以下方式使class可再利用:
* mixin
* extension methods
* extension type
* implements
* extends
### 類別成員
instance member:
* 物件變數
* 物件方法
* **實作的介面**
class member:
* static variable
* static method
使用點 ( . ) 來引用實例或類別的變數或方法
### 使用建構函數初始化物件
Constructor names can be either ClassName or ClassName.identifier.
```
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
```
若要使用常數建構函式建立編譯時常數,請將const關鍵字放在建構函式名稱之前:
`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!
```
### 取得物件的類型
```
print('The type of a is ${a.runtimeType}');
assert(a is int); // 推薦
```
### Instance variables
```
class Point {
double? x; // 可空變數初始值是null
double y;
double z = 0; // 不可空變數必須設定初始值(或用constructor來初始)
Point(this.y);
}
```
實例變數都會產生隱式getter方法。非final or late final變數會產生隱式setter方法.
非late實例變數在物件初始化(建構函式)之前就要賦值, 此時this是不存在的.
```
double initialX = 1.5;
class Point {
// OK, 可以用全域變數來賦值
double? x = initialX;
// ERROR, 此時實例還不存在
double? y = this.x;
// OK, 只有在使用z時才會檢查, 那時實例已經建立
late double? z = this.x;
// OK, `this.x` and `this.y` are parameter declarations, not expressions:
Point(this.x, this.y);
}
```
### class本身就是接口
把一個class當接口時, 要實作其所有實例成員(實例的變數和方法, 簽名必須一樣)
```
class Person {
String _name;
Person(this._name);
void intro() => print('Person name: $_name');
}
class Student implements Person {
String _name;
String _id;
Student(this._name, this._id);
void intro() => print('Student name: $_name, ID: $_id');
}
class CollegeStudent implements Student {
String _name;
String _id;
int _age;
CollegeStudent(this._name, this._id, this._age);
void intro() => print('College student name: $_name, ID: $_id, age: $_age');
}
void main() {
var bob = CollegeStudent("Bob Smith", '123456', 19);
bob.intro();
}
```
```
// class B實作接口class A
// 則B是A的subclass
class A {
int a;
A(int b) : a = b;
}
class B implements A {
int a;
int b;
B(this.a, this.b);
}
void main() {
var aa = A(23);
print(aa.a);
var bb = B(12, 45);
print(bb.b);
assert(bb is A);
assert (bb is B);
// assert(aa is B);
}
```
可以實作多個接口
`class Point implements Comparable, Location {...}`
### 類別(靜態)變數和方法
使用`static`宣告變數或方法為類別所有, 用類別調用, 不是用實例調用.
靜態方法可以讀取靜態變數
```
class Circle {
static const pi = 3.14159;
int originX, originY;
Circle(this.originX, this.originY);
// 不能讀取originX, originY, 但可直接讀取類別變數pi
static num area(num radius) => pi * radius * radius;
}
void main() {
num area = Circle.area(12);
print(area); // 452.38895999999994
}
```