3rd term 2nd week - dsuz/csharp GitHub Wiki
-
拡張メソッド
-
ユーザー定義型(自分で作ったクラスや構造体)に機能を追加する
- IComparable インターフェイスを継承して比較可能にする
- 演算子をオーバーロードして新たな演算を定義する
- ToString() をオーバーライドしてログ出力などをしやすくする
以下のアセットを Unity プロジェクトにインポートします
既存のクラスに自分で作ったメソッドを追加することができる。この時、追加したメソッドを「拡張メソッド」と呼ぶ。拡張メソッドは以下のように書いて追加することができる。
static class '適当なクラス名'
{
public static '戻り値の型' 'メソッド名'(this '拡張したいクラスの名前' '引数の変数名', 'メソッドの引数の型1' 'メソッドの引数の変数名1', ...)
{
// 拡張メソッドの処理をここに書く
}
}
以下は、Vector3 クラスに、指定した座標との距離を求めるインスタンスメソッド Distance() (※2)を拡張メソッドとして追加するコードである。
using UnityEngine;
/// <summary>
/// 拡張メソッドを定義する
/// </summary>
static class Vector3Extensions
{
/// <summary>
/// インスタンスを起点座標とし、destination を終点座標として起点から終点までの距離を求める
/// </summary>
/// <param name="origin">起点座標</param>
/// <param name="destination">終点座標</param>
/// <returns></returns>
public static float Distance(this Vector3 origin, Vector3 destination)
{
return Vector3.Distance(origin, destination);
}
}
(※2)Vector3 クラスには、2点間の距離を求める static メソッド Distance() は既にある。
実際は拡張メソッドは既に使っている。例えば、Linq は既存のクラスに追加された拡張メソッドである。DOTween は Transform, Rigidbody, Camera, Light, Material 等に拡張メソッドを追加している。
自分で作った型をユーザー定義型 (user-defined types, UDT) と言います。カスタム クラスとか自作クラスとも言います。ただし、構造体も型ですから、ユーザー定義型というのが正確です。
Unity 上で C# でコンポーネントを作った時、コンポーネントはクラスですから、コンポーネントはユーザー定義型です。
もちろん Unity 上でも、MonoBehaviour を継承せずにユーザー定義型を作って、データを扱うための型を定義することができます。
ユーザー定義型を作った時、今回学ぶことをしておかないといろいろと不便な事があります。例えば、Vector3 は Unity によって定義されている構造体ですが、Vector3 と Vector3 は足すことができます。しかし、Vector3 と Vector3 は比較することができません。なぜならそれは定義されていないからです。また、Vector3.ToString() を呼ぶと、戻り値として (x, y, z) の形式で x 要素, y 要素, z 要素を文字列で受け取れます。これによりログ出力した時に見やすくなります。
このように、自分で作ったユーザー定義型にも 比較・演算・文字列への変換を定義しておくことでデータの操作等が簡単にできるようになります。
IComparable インターフェイスを継承して CompareTo メソッドを実装することにより、そのクラスのインスタンスはソート可能になる。CompareTo メソッドは object 型を引数にとり、int 型の値を返す。
引数として受け取る object 型の値は、現在のインスタンスと比較するインスタンスであり、戻り値としては、以下の要領で「負の値」「0」「「正の値」を返す。
- 現在のインスタンスを比較対象のインスタンスより昇順ソートの順番で前としたい時、負の値を返す
- 現在のインスタンスを比較対象のインスタンスより昇順ソートの順番で後ろとしたい時、正の値を返す
- 現在のインスタンスと比較対象のインスタンスを昇順ソートの順番で同じ、としたい時、0 を返す
今回のサンプルでそれを実装しているのは MyCustomClass.CompareTo() です。これにより、ボタンをクリックして DataLoader.SortGearData() を呼び出した時に Sort() メソッドで簡単にソートすることができるようになります。このサンプルでは Gear クラスを ID 順でソートするように定義してあります。
ユーザー定義型に対して演算を定義したいことがある。そのような時、オーバーロード可能な演算子 に挙げられている演算子はオーバーロードして自分で演算を定義することができる。
今回のサンプルでは MyCustomClass で Gear 同士の足し算を定義しています。Gear はアイテム(装備)のデータですが、足し算によりアイテムを「合成」し、和として新たなアイテムが得られるようにしています。得られるアイテムはランダムです。ボタンをクリックして InventoryTest.Fusion() を呼び出した時にアイテムを合成しています。
条件式等でユーザー定義型のインスタンス同士を比較したい時は、等号・不等号をオーバーロードしてやればよいです。
ToString() メソッドの一般的な役割は、「インスタンスの文字列表現を返す」である。UnityEngine.Vector3 や UnityEngine.Color, System.DateTime などがわかりやすい。
ユーザー定義型でも、そのクラスのインスタンスに格納されているデータの文字列による表現を簡単にわかりやすく取り出したいケースは頻繁にある。そのような場合は、適宜 ToString() メソッドをオーバーライドし、適切な文字列表現を返す処理を追加する。
-
拡張メソッド
- 独習 C# 8.2.9 拡張メソッド
-
演算子のオーバーロード
- 独習 C# 9.7 - 演算子のオーバーロード
-
ToString() メソッドのオーバーライド
- 独習 C# 9.6.2 - オブジェクトの文字列表現を取得する ― ToString メソッド