インタフェース
書ける形(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 による実装 |
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 => ... } | 既定のケースを置かない分岐 |
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 | 設計 | 同上 |
| 値型に付けたインタフェースは、ローカル変数・引数・戻り値・配列に置けます。フィールドには置けません。 | ||||
| Behaviour に付けたインタフェースは、フィールドにも配列にも置けて、null と比べられます。 |
値型に付けたインタフェースの値は、union(直和型)と同じ形に変換されます。いま入って いるのがどの型かを表す番号 1 つと、型ごとの置き場を並べたものです。書けない形が union とそろって いるのはこのためです。Behaviour に付けたインタフェースはこの形ではなく、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 もインタフェースを実装できます。this を、そのインタフェースの型の変数へ入れられます。
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 “インタフェース型の配列での保持”編集画面から複数の 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 “既定のケースを置かない分岐”実装した型のケースを尽くしていれば、既定のケースは要りません。union と同じです。
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(); }}