Part19:プロトコル

続・おまけ

海未「破廉恥です!破廉恥です!!破廉恥です!!!」
希(予想以上のすごい剣幕や)
海未「何なのですかあれは!?女の子同士、それも小学生が、あ、あんなこと・・・」
凜(うんうん、顔真っ赤にして取り乱す海未ちゃん、やっぱりかわいいにゃ)
海未「百合にとどまらず、BLとか・・・美々の名台詞に共感しそうになってしまったではないですか・・・」
希(あ、なんだかんだで3期まで見とるな)
海未「東條希!」
希「は、はいっ!?」
海未「分かっていて勧めましたね?そこへ直りなさい!成敗します!」
希「・・・くっ、殺せ!」
海未「いいえ、殺すなんてもったいない」
希「いやああああああああああああああああああああっ!!」


本編?ここから

希「・・・う、海未ちゃんにワシワシMAXされるとは・・・不覚」
凜「希ちゃん、希ちゃん、しっかりするにゃ!」
海未「私がやったことですが・・・今回、希は無理そうですね」
凜「そんなこともあろうかと、凜も予習してきたにゃ!」
海未「!凜、気が利くではないですか」
凜「あとは凜に任せて、希上等兵はゆっくり休むにゃ!」
希「あ、あとは頼んだで、凜二等兵・・・がくっ」
凜「というわけで海未軍曹!今日は凜二等兵が担当するであります!」


今度こそ本編ここから

凜「ではプロトコルの説明を始めるにゃ」
海未「はい。よろしくお願いします」
凜「これまで出てきたリストとマップ、両方ともEnumモジュールの関数が使えたのは覚えてるかにゃ?」
海未「mapやreduceなどはどちらにも使えました」
凜「うん。それはね、リストもマップもEnumerableというプロトコルを実装しているからなんだ」
海未「前にEnumerableとStreamのところで出てきた話ですが、Enumerableなデータ構造というのはEnumerableプロトコルを実装したデータ構造と考えればいいのですね」
凜「多態性とかポリモルフィズムとかそういうのをEliixrで表現するための仕組み、なんだって」
海未「ちょっと、よくわかりません・・・」
凜「たとえば自転車にゃ。ハンドルとブレーキとペダルがついていれば、あとはどんな代物であろうと自転車として運転できるにゃ」
海未「そのハンドルとブレーキとペダルがプロトコルだということですか?」
凜「そんな感じにゃ。Enumerableプロトコルで決められた関数を実装した構造体は、中身が何であれEnumモジュールの関数で扱えるにゃ」
海未「自作の構造体でも、Enumerableを実装すればよいのですか?」
凜「そうにゃ。ちょっと例に出すにはめんどくさいから、代わりにプロトコルを自分で作って、構造体に実装してみるにゃ」

defmodule SchoolIdol do
  defstruct name: "", age: 0, school: ""
end

defmodule ProfessionalIdol do
  defstruct name: "", age: 0
end

defmodule StreetSinger do
  defstruct name: ""
end

defprotocol Idol do
  def introduce idol
end

defimpl Idol, for: SchoolIdol do
  def introduce idol do
    "#{idol.school}所属、#{idol.name}#{idol.age}歳です♪"
  end
end

defimpl Idol, for: ProfessionalIdol do
  def introduce idol do
    "#{idol.name}#{idol.age}歳です☆"
  end
end

defmodule Main do
  require SchoolIdol
  require ProfessionalIdol
  require StreetSinger

  def info do
    umi = %SchoolIdol{name: "園田海未", age: 16, school: "音ノ木坂学院"}
    yukari = %ProfessionalIdol{name: "田村ゆかり", age: 17}
    honoka = %StreetSinger{name: "高坂穂乃果"}

    IO.puts Idol.introduce umi
    IO.puts Idol.introduce yukari
    IO.puts Idol.introduce honoka
  end
end

Main.info

凜「長くなったので上から順に解説するよ。まず、defmoduleで構造体を3つ定義してるにゃ。これにプロトコルを実装していくにゃ」
海未「ここまでは、変わったところはありませんね」

凜「次のdefprotocolがプロトコルの定義にゃ。Idolってプロトコルで、これを実装した構造体はそれっぽい自己紹介ができることにするよ」
海未「def introduce idolというのは、do~endブロックのない関数定義ですか?」
凜「うん。関数の名前と引数だけ決めて、中身はそれぞれの構造体の側で決めるにゃ」
海未「プロトコル自体が実装を持つわけではないのですね」

凜「次のdefimplで、構造体にプロトコルを実装するにゃ。ここではSchoolIdolとProfessionalIdolの2つの構造体に実装して、StreetSingerには実装しないことにするにゃ」
海未「ここで定義しているのが関数の本体ですね」
凜「うん。SchoolIdolとProfessionalIdolで実装が違うのがポイントにゃ」

凜「最後は、ここまで用意した構造体とプロトコルを使ってみるにゃ」
海未「requireというのは初めて見ましたが」
凜「モジュールの中で、他のモジュールを使う場合にrequire モジュール名って書くにゃ」
海未「プロトコルは書かなくてよいのですか?」
凜「なんか大丈夫っぽいにゃ」

凜「実行結果はこうなるにゃ」

$ elixir lw.exs
音ノ木坂学院所属、園田海未、16歳です♪
田村ゆかり、17歳です☆
** (Protocol.UndefinedError) protocol Idol not implemented for %StreetSinger{name: "高坂穂乃果"}
    lw.exs:13: Idol.impl_for!/1
    lw.exs:14: Idol.introduce/1
    lw.exs:41: Main.info/0
    (elixir) lib/code.ex:307: Code.require_file/2

凜「全部同じIdol.introduce関数を使ってるんだけど、海未ちゃんとゆかり姫では違う処理が動いてるにゃ」
海未「呼び出し方はプロトコルで決まっていて、実際の処理は構造体ごとに変わるのですね」
凜「そしてNYの都市伝説穂乃果ちゃんはIdolを実装してないからエラーになるにゃ」

海未「Enumerableの場合も、Enumerableプロトコルで定められた呼び出し方で、リストとマップで違う処理が実行されているわけですね」
凜「分かってくると面白いにゃ」

海未「次回は希に罪滅ぼしとして内包表記をやってもらいます」
希「なんか難しそうなところやん・・・」

凜「今回はおまけなしかな?」
海未「また関節を外されたいのですか?」
凜「・・・なんでもないにゃ」


LINEで送る
Pocket