Dartの継承はそんなにむずくない。怖くないはず。まだ良くわかってないから1個ずつ理解するためにまとめる。
仕様的なはなし
-
多段継承多重継承しないはず- 追記)多段継承は普通にできます
-
interface
宣言は無い。class
宣言が暗黙的にinterface
になる的なやつ-
interface
したけりゃ実装無しのabstract
にすればいいはず
-
-
Generics
が使える -
extends
とimplements
がある
Basic extends
class Parent {
String getName() {
return 'parent';
}
}
class Child extends Parent {
String getName() {
return "child [Not ${super.getName()}]";
}
}
main(){
print(new Child().getName());
//> child [Not parent]
}
Private property
dartのprivate
/public
は名前の先頭に _
があるかどうかで決まる。
protected
は無いって噂だしきっと親のprivateプロパティにはアクセスできないじゃないかな。
class Parent {
String _name = 'parent';
String getName() {
return this._name;
}
}
class Child extends Parent {
String getName1() {
return "child [Not ${super.getName()}]";
}
String getName2() {
return "child [Not ${super._name}}";
}
}
main(){
Child child = new Child();
print(child.getName1());
print(child.getName2());
print(child._name);
//> child [Not parent]
//> child [Not parent}
//> parent
}
あれ、アクセスできた。なんでやねん。
libraryが一緒だとアクセスできちゃうらしい。なるほど。
import './child.dart';
main(){
Child child = new Child();
print(child.getName1());
//> child [Not parent]
print(child.getName2());
//> Unhandled exception: Class 'Child' has no instance getter '_name'.
print(child._name);
//> Unhandled exception: Class 'Child' has no instance getter '_name'.
}
class Parent {
String _name = 'parent';
String getName() {
return this._name;
}
}
import './parent.dart';
class Child extends Parent {
String getName1() {
return "child [Not ${super.getName()}]";
}
String getName2() {
return "child [Not ${super._name}}";
}
}
ちゃんとエラーでてくれる。すばら。
というか library を明示的にかかなけりゃ別library的な扱いになるのかねぇ。ファイル分割しただけなんだけど。
implements
class Parent {
String getName() {
return 'parent';
}
}
class Child implements Parent {
String getName() {
return "child [Not ${super.getName()}]";
}
}
main(){
print(new Child().getName());
//> Unhandled exception: Super class of class 'Child' has no instance method 'getName'.
}
うん。super使えないね。
implements errors
implementsってくらいだから実装なかったら死ぬはず。
class Parent {
String getName();
}
class Child implements Parent {
}
main(){
print(new Child());
//> Instance of 'Child'
}
あれ、getNameの実装をChildに求めたはずなのに特に怒られない。
abstract class Parent
とかしても関係ない。
あるぇー?
$ dartanalyzer main.dart
Analyzing [main.dart]...
[warning] Missing concrete implementation of 'Parent.getName' (/path/to/main.dart, line 5, col 7)
1 warning found.
なるほど。dartanalyzerだとエラーになるけど、コンパイル時にはエラーにならないのか。
この辺もOptional Types
の方針なのかな。
という事は、CIでdartanalyzer
回すようにしないといけないだろうね。
IDEでは一応エラーになってたから、開発中に全く気づけ無いという事はなさそう。
generics
import 'dart:mirrors';
abstract class Family {
String getName();
String getFamilyName() {
return 'yamada';
}
}
class Child extends Family {
String getName() {
return 'taro';
}
}
class Parent extends Family {
String getName() {
return 'hanako';
}
}
class Member<T extends Family> {
String getFullName(){
ClassMirror cm = reflectClass(T);
T t = cm.newInstance(const Symbol(''), []).reflectee;
return "${t.getName()} ${t.getFamilyName()}";
}
}
main() {
print(new Member<Child>().getFullName());
//> taro yamada
print(new Member<Parent>().getFullName());
//> hanako yamada
}
使い方として合ってるかしらんけど、こんな感じの事ができるらしい。
generics
をextends
周りで使う意味とかやり方とかを理解してない。
でもreflect
が出てきてる時点であんま良くない気がする。
Family
をextends
したParent
とChild
がいて、それらを受け取る?事ができるMember<T extends Family>
がいて、Member
の中からはT
がParent
だったりChild
だったりするので、reflect
でインスタンス取得してアレコレする的な?
with (mix-in)
class Family {
String getFamilyName() {
return 'yamada';
}
}
class Parent {
String getName() {
return 'taro';
}
}
class Child extends Parent with Family {
String getName() {
return '${super.getName()} ${super.getFamilyName()}';
}
}
main() {
print(new Child().getName());
//> taro yamada
}
with
でMix-inできるみたい。でもextends
は必ず必要。
extends
いらないような場合はObject
をextends
すればいいらしい。
class Family {
String getFamilyName() {
return 'yamada';
}
}
class Child with Family {
String getName() {
return '${super.getFamilyName()}';
}
}
main() {
print(new Child().getName());
}
//>[error] The with clause cannot be used without an extends clause
ちょくwith
はエラーだけど、
class Family {
String getFamilyName() {
return 'yamada';
}
}
class Child extends Object with Family {
String getName() {
return '${super.getFamilyName()}';
}
}
main() {
print(new Child().getName());
//> yamada
}
extends Object
する事で動作を変えずに継承無しのMix-inができる。Good。
まとめ
- 何か想像と挙動違うとこある
- Genericsがよくわからない
- 思ったよりむずかった
- まだ理解が足りないので追加で勉強だなー