クラス
Dartは、クラスとmixinベースの継承を持つオブジェクト指向言語です。 Null
を除くすべてのオブジェクトはクラスのインスタンスであり、Null
を除くすべてのクラスはObject
を継承します。 mixinベースの継承とは、(トップクラスであるObject?
を除く)すべてのクラスは正確に1つのスーパークラスを持つものの、クラスの本体は複数のクラス階層で再利用できることを意味します。 拡張メソッドは、クラスを変更したり、サブクラスを作成することなく、クラスに機能を追加する方法です。 クラス修飾子を使用すると、ライブラリがクラスをサブタイプ化する方法を制御できます。
クラスメンバの使用
#オブジェクトは、関数とデータ(それぞれメソッドとインスタンス変数)からなるメンバを持っています。 メソッドを呼び出す場合、オブジェクト上でそれを呼び出します。メソッドはそのオブジェクトの関数とデータにアクセスできます。
インスタンス変数またはメソッドを参照するには、ドット(.
)を使用します。
var p = Point(2, 2);
// Get the value of y.
assert(p.y == 2);
// Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));
最左オペランドがnullの場合に例外を回避するには、.
の代わりに?.
を使用します。
// If p is non-null, set a variable equal to its y value.
var a = p?.y;
コンストラクタの使用
#コンストラクタを使用してオブジェクトを作成できます。コンストラクタ名は、ClassName
またはClassName.identifier
のいずれかです。たとえば、次のコードはPoint()
とPoint.fromJson()
コンストラクタを使用してPoint
オブジェクトを作成します。
var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});
次のコードは同じ効果がありますが、コンストラクタ名の前にオプションのnew
キーワードを使用しています。
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
一部のクラスは定数コンストラクタを提供します。定数コンストラクタを使用してコンパイル時定数を作成するには、コンストラクタ名の前にconst
キーワードを付けます。
var p = const ImmutablePoint(2, 2);
2つの同一のコンパイル時定数を構築すると、単一の標準インスタンスになります。
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // They are the same instance!
定数コンテキスト内では、コンストラクタまたはリテラルの前にconst
を省略できます。たとえば、constマップを作成する次のコードを見てください。
// Lots of const keywords here.
const pointAndLine = const {
'point': const [const ImmutablePoint(0, 0)],
'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};
const
キーワードの最初の使用を除いてすべて省略できます。
// Only one const, which establishes the constant context.
const pointAndLine = {
'point': [ImmutablePoint(0, 0)],
'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};
定数コンストラクタが定数コンテキストの外側にあり、const
なしで呼び出された場合、非定数オブジェクトが作成されます。
var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant
assert(!identical(a, b)); // NOT the same instance!
オブジェクトの型の取得
#実行時にオブジェクトの型を取得するには、Type
オブジェクトを返すObject
プロパティruntimeType
を使用できます。
print('The type of a is ${a.runtimeType}');
ここまで、クラスの使用方法を見てきました。このセクションの残りの部分では、クラスの実装方法を示します。
インスタンス変数
#インスタンス変数の宣言方法は次のとおりです。
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
double z = 0; // Declare z, initially 0.
}
初期化されていないインスタンス変数は、nullable型で宣言されている場合、値はnull
になります。nullableでないインスタンス変数は、宣言時に初期化されなければなりません。
すべてのインスタンス変数は、暗黙的なゲッターメソッドを生成します。初期化子がない非finalインスタンス変数とlate final
インスタンス変数は、暗黙的なセッターメソッドも生成します。詳細については、ゲッターとセッターを参照してください。
class Point {
double? x; // Declare instance variable x, initially null.
double? y; // Declare y, initially null.
}
void main() {
var point = 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.
}
宣言場所で非late
インスタンス変数を初期化すると、コンストラクタとその初期化子リストが実行される前に、インスタンスが作成されるときに値が設定されます。その結果、非late
インスタンス変数の初期化式(=
の後)ではthis
にアクセスできません。
double initialX = 1.5;
class Point {
// OK, can access declarations that do not depend on `this`:
double? x = initialX;
// ERROR, can't access `this` in non-`late` initializer:
double? y = this.x;
// OK, can access `this` in `late` initializer:
late double? z = this.x;
// OK, `this.x` and `this.y` are parameter declarations, not expressions:
Point(this.x, this.y);
}
インスタンス変数はfinal
にすることができ、その場合は正確に1回だけ設定する必要があります。final
、非late
インスタンス変数は、宣言時、コンストラクタパラメータを使用するか、コンストラクタの初期化子リストを使用して初期化します。
class ProfileMark {
final String name;
final DateTime start = DateTime.now();
ProfileMark(this.name);
ProfileMark.unnamed() : name = '';
}
コンストラクタ本体の開始後にfinal
インスタンス変数の値を代入する必要がある場合は、次のいずれかを使用できます。
- ファクトリコンストラクタを使用します。
late final
を使用しますが、注意してください:初期化子がないlate final
はAPIにセッターを追加します。
暗黙的インターフェース
#すべてのクラスは、クラスのすべてのインスタンスメンバと、それが実装するインターフェースのすべてのインスタンスメンバを含むインターフェースを暗黙的に定義します。Bの実装を継承せずにBのAPIをサポートするクラスAを作成する場合は、クラスAがBインターフェースを実装する必要があります。
クラスは、implements
句で1つ以上のインターフェースを宣言し、インターフェースで要求されるAPIを提供することで、1つ以上のインターフェースを実装します。例:
// A person. The implicit interface contains greet().
class Person {
// In the interface, but visible only in this library.
final String _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(String who) => 'Hello, $who. I am $_name.';
}
// An implementation of the Person interface.
class Impostor implements Person {
String get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
クラスが複数のインターフェースを実装することを指定する例を次に示します。
class Point implements Comparable, Location {...}
クラス変数とクラスメソッド
#static
キーワードを使用して、クラス全体の変数とメソッドを実装します。
静的変数
#静的変数(クラス変数)は、クラス全体の状態と定数に役立ちます。
class Queue {
static const initialCapacity = 16;
// ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
静的変数は、使用されるまで初期化されません。
静的メソッド
#静的メソッド(クラスメソッド)はインスタンスに対して動作せず、そのためthis
にアクセスできません。ただし、静的変数にはアクセスできます。次の例に示すように、静的メソッドはクラスで直接呼び出します。
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
静的メソッドをコンパイル時定数として使用できます。たとえば、静的メソッドを定数コンストラクタのパラメータとして渡すことができます。
特に明記されていない限り、このサイトのドキュメントはDart 3.5.3を反映しています。ページの最終更新日:2024年5月30日。 ソースを表示 または 問題を報告する。