インタフェース
対応(23)
Section titled “対応(23)”| 書き方 | 説明 | 注意 |
|---|---|---|
interface IShape { float Area(); } | インタフェースの宣言と実装 | 本体を書くとエラーになります(非対応)。 |
interface IValue { int Id { get; } } | インタフェースのプロパティ | |
public int Id { get { return 1; } } | 計算して返すプロパティの実装 | 明示的な実装にすると書けません(非対応)。 |
interface IFast : IGadget | インタフェースどうしの継承 | |
struct Box : IShape | 値型による実装 | |
record Tag(int N) : ILabel | record による実装 | |
class C : TsukimiBehaviour, IGadget | Behaviour による実装 | this を、そのインタフェースの型の変数へ代入できます。 |
struct Both : IGadget, IReset | 値型による複数の実装 | |
class C : TsukimiBehaviour, IGadget, IReset | Behaviour による複数の実装 | |
IShape s = new Box(); | ローカル変数での保持 | |
void Use(IShape s) | 引数での受け取り | |
IShape Make() | 戻り値での返却 | |
IShape[] all = new IShape[2]; | インタフェースの配列への値型の格納 | |
public IGadget other; | インタフェース型のフィールドでの保持 | |
other is IReset | 別のインタフェースへの型テスト | 値型を代入したインタフェースでは書けません(非対応)。 |
public IGadget[] all; | インタフェース型の配列での保持 | |
GetComponent<IGadget>() | インタフェースを指定した取得 | |
other != null | null との比較 | |
other?.Tick() | null 条件の呼び出し | |
s is Box | 具象の型の判定 | 別のインタフェースを実装しているかは見られません(非対応)。 |
s switch { Box b => ..., _ => ... } | 具象の型による分岐 | |
s switch { Box b => ..., Dot d => ... } | 既定のケースを置かない分岐 | union と同じです。 |
where T : IShape | インタフェースによる型引数の制約 |
非対応(9)
Section titled “非対応(9)”| 書き方 | 説明 | エラー | 理由 | 代替 |
|---|---|---|---|---|
int IValue.Id { get { return 1; } }(実装する側) | インタフェースのプロパティを明示的に実装する | TUKI0001 | 設計 | public のプロパティとして実装する |
v.Id(v は Behaviour に付けたインタフェース) | Behaviour に付けたインタフェースのプロパティを読む | TUKI0001 | 設計 | インタフェース側をメソッド(int Id();)にする(値型の実装ならプロパティのまま読める) |
int Twice() { return Value() * 2; } | インタフェースに既定の実装を書く | TUKI0001 | 設計 | 実装する側それぞれに書く |
float IShape.Area() { ... } | 明示的に実装する | TUKI0001 | 設計 | 普通の public メソッドとして実装する |
private IShape held; | 値型に付けたインタフェースをフィールドに持つ | TUKI0001 | 未実装 | ローカル変数・引数で受け渡す。Behaviour に付けたものならフィールドに持てる |
Box b = (Box)s; | インタフェースから具象へキャストする | TUKI0001 | 未実装 | 型パターン(s switch { Box b => ... })で受ける |
IGadget g = new Widget(); g is IReset | 値型を代入したインタフェースへの型テスト | TUKI0001 | 未実装 | Behaviour に付けたインタフェースで受けるか、具象の型で見る |
IShape s = new Box(); s == null | 値型に付けたインタフェースを null と比べる | TUKI0001 | 設計 | Behaviour に付けたインタフェースで受ける(値型の値は null にならない) |
IShape s = new Box(); s?.Area() | 値型に付けたインタフェースに ?. を使う | TUKI0001 | 設計 | 同上 |
| 置ける場所 | 内部表現 | |
|---|---|---|
| 値型に付けたインタフェース | ローカル変数・引数・戻り値・配列。フィールドには置けません | union(直和型)と同じ形(いま入っている型を表す番号 1 つと、型ごとのヒープ変数)。非対応が union とそろっているのはこのためです |
| Behaviour に付けたインタフェース | フィールドにも配列にも置けて、null と比べられます | Behaviour そのものを指します |
インタフェースの宣言
Section titled “インタフェースの宣言”インタフェースの宣言と実装
Section titled “インタフェースの宣言と実装”インタフェースに置けるのは、メソッドとプロパティの宣言だけです。
using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceDeclare : TsukimiBehaviour{ void Start() { IShape s = new Box(); Debug.Log(s.Area()); // => 1 }}インタフェースのプロパティ
Section titled “インタフェースのプロパティ”using UnityEngine;using Tsukimi;
public interface IValue{ int Id { get; }}
public struct Num : IValue{ public int Id { get; set; }}
public class IfProperty : TsukimiBehaviour{ void Start() { IValue v = new Num { Id = 7 }; Debug.Log(v.Id); // => 7 }}計算して返すプロパティの実装
Section titled “計算して返すプロパティの実装”値型の実装は、本体を書くプロパティでもかまいません。
using UnityEngine;using Tsukimi;
public interface IValue{ int Id { get; }}
public struct Num : IValue{ public int Id { get { return 1; } }}
public class R_props : TsukimiBehaviour{ void Start() { IValue v = new Num(); Debug.Log(v.Id); // => 1 }}インタフェースどうしの継承
Section titled “インタフェースどうしの継承”using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public interface IFast : IGadget{ void Boost();}
public struct Runner : IFast{ public void Tick() { Debug.Log(1); } // => 1 public void Boost() { Debug.Log(2); } // => 2}
public class IfaceInherit : TsukimiBehaviour{ void Start() { IFast f = new Runner(); f.Tick(); f.Boost(); }}インタフェースの実装
Section titled “インタフェースの実装”値型による実装
Section titled “値型による実装”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceStructImplements : TsukimiBehaviour{ void Start() { Box b = new Box(); IShape s = b; Debug.Log(s.Area()); // => 1 }}record による実装
Section titled “record による実装”using UnityEngine;using Tsukimi;
public interface ILabel{ int Id();}
public record Tag(int N) : ILabel{ public int Id() { return N; }}
public class IfaceRecordImplements : TsukimiBehaviour{ void Start() { ILabel l = new Tag(1); Debug.Log(l.Id()); // => 1 }}Behaviour による実装
Section titled “Behaviour による実装”Behaviour もインタフェースを実装できます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceBehaviourImplements : TsukimiBehaviour, IGadget{ public void Tick() { Debug.Log(1); }
void Start() { IGadget g = this; g.Tick(); }}値型による複数の実装
Section titled “値型による複数の実装”using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public interface IReset{ void Reset();}
public struct Both : IGadget, IReset{ public void Tick() { Debug.Log(1); } // => 1 public void Reset() { Debug.Log(2); } // => 2}
public class IfaceStructMultipleInterfaces : TsukimiBehaviour{ void Start() { Both b = new Both(); IGadget g = b; IReset r = b; g.Tick(); r.Reset(); }}Behaviour による複数の実装
Section titled “Behaviour による複数の実装”Behaviour でも、複数のインタフェースを実装できます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public interface IReset{ void Reset();}
public class IfaceBehaviourMultipleInterfaces : TsukimiBehaviour, IGadget, IReset{ public void Tick() { Debug.Log(1); } // => 1
public void Reset() { Debug.Log(2); } // => 2
void Start() { Tick(); Reset(); }}値としての保持
Section titled “値としての保持”ローカル変数での保持
Section titled “ローカル変数での保持”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceLocalVariable : TsukimiBehaviour{ void Start() { IShape s = new Box(); Debug.Log(s.Area()); // => 1 }}引数での受け取り
Section titled “引数での受け取り”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceParameter : TsukimiBehaviour{ void Start() { Use(new Box()); }
private void Use(IShape s) { Debug.Log(s.Area()); // => 1 }}戻り値での返却
Section titled “戻り値での返却”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceReturnValue : TsukimiBehaviour{ void Start() { IShape s = Make(); Debug.Log(s.Area()); // => 1 }
private IShape Make() { return new Box(); }}インタフェースの配列への値型の格納
Section titled “インタフェースの配列への値型の格納”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceArrayOfValues : TsukimiBehaviour{ void Start() { IShape[] all = new IShape[2]; all[0] = new Box(); all[1] = new Box(); float total = 0f; for (int i = 0; i < all.Length; i++) { total += all[i].Area(); } Debug.Log(total); // => 2 }}インタフェース型のフィールドでの保持
Section titled “インタフェース型のフィールドでの保持”Behaviour に付けたインタフェースは、フィールドに持てます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceBehaviourField : TsukimiBehaviour, IGadget{ public IGadget other;
public void Tick() { }
void Start() { other.Tick(); }}別のインタフェースへの型テスト
Section titled “別のインタフェースへの型テスト”Behaviour に付けたインタフェースなら、別のインタフェースを実装しているかを見られます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public interface IReset{ void Reset();}
public class R_isc : TsukimiBehaviour, IGadget{ public IGadget other;
public void Tick() { }
void Start() { bool b = other is IReset; Debug.Log(b); }}インタフェース型の配列での保持
Section titled “インタフェース型の配列での保持”Inspector から複数の Behaviour を差し込んで、1 つのループで回せます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceBehaviourArray : TsukimiBehaviour, IGadget{ public IGadget[] all;
public void Tick() { }
void Start() { for (int i = 0; i < all.Length; i++) { all[i].Tick(); } }}取得と null
Section titled “取得と null”インタフェースを指定した取得
Section titled “インタフェースを指定した取得”型引数にインタフェースを指定して、それを実装した Behaviour を取れます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceGetComponent : TsukimiBehaviour, IGadget{ public void Tick() { }
void Start() { IGadget g = GetComponent<IGadget>(); if (g != null) { g.Tick(); } }}null との比較
Section titled “null との比較”Behaviour に付けたインタフェースに対してだけ使えます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceCompareNull : TsukimiBehaviour, IGadget{ public IGadget other;
public void Tick() { }
void Start() { Debug.Log(other == null); // => true if (other != null) { other.Tick(); } }}null 条件の呼び出し
Section titled “null 条件の呼び出し”?. も、Behaviour に付けたインタフェースに対してだけ使えます。
using UnityEngine;using Tsukimi;
public interface IGadget{ void Tick();}
public class IfaceNullConditional : TsukimiBehaviour, IGadget{ public IGadget other;
public void Tick() { }
void Start() { other?.Tick(); }}型による分岐
Section titled “型による分岐”具象の型の判定
Section titled “具象の型の判定”具象の型かどうかを判定します。
using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceIsConcrete : TsukimiBehaviour{ void Start() { IShape s = new Box(); bool isBox = s is Box; Debug.Log(isBox); // => true }}具象の型による分岐
Section titled “具象の型による分岐”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public struct Dot : IShape{ public float Area() { return 0f; }}
public class IfaceSwitchTypePattern : TsukimiBehaviour{ void Start() { IShape s = new Box(); float a = s switch { Box b => b.Area(), Dot d => d.Area(), _ => 0f, }; Debug.Log(a); // => 1 }}既定のケースを置かない分岐
Section titled “既定のケースを置かない分岐”実装した型のケースを尽くしていれば、既定のケースは必要ありません。
using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public struct Dot : IShape{ public float Area() { return 0f; }}
public class IfaceSwitchExhaustive : TsukimiBehaviour{ void Start() { IShape s = new Box(); float a = s switch { Box b => b.Area(), Dot d => d.Area(), }; Debug.Log(a); // => 1 }}ジェネリック
Section titled “ジェネリック”インタフェースによる型引数の制約
Section titled “インタフェースによる型引数の制約”using UnityEngine;using Tsukimi;
public interface IShape{ float Area();}
public struct Box : IShape{ public float Area() { return 1f; }}
public class IfaceGenericConstraint : TsukimiBehaviour{ void Start() { Debug.Log(Measure(new Box())); // => 1 }
private float Measure<T>(T shape) where T : IShape { return shape.Area(); }}