構造型指向(SOP) か 公称型指向(NOP) か、それを知りたい ~ 構造型と公称型 ~

**[「シコウ」を語る Advent Calendar 2021](https://qiita.com/advent-calendar/2021/shikou_poem)** 1日目の記事です。

# はじめに

https://ja.m.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0

> プログラミングパラダイムは、プログラマにプログラムの見方を与えるものと言える。

オブジェクト指向プログラミング、関数型プログラミングなどなど、
**プログラムパラダイムの記事は好きですか？** 

私は、 **苦手ですが、好き** です。

苦手な理由は、 **バズワードの要素があり、定義が曖昧[^1]** なところ。
好きな理由は、 **色々な考え方に触れ、嗜好が分かる** ところ。

[^1]: とはいえ、プログラミング全般に関連した話題については、話者や時代により具体的なプログラミング言語のバックボーンが異なるため、定義が曖昧になることは避けられないとも考えています。

例えば、今年話題になった、プログラミング言語を、
手続き型と関数型、静的型付けと動的型付けで分類する以下の記事

https://qiita.com/danwatanabe/items/b2dae4b73f6c18056f3d

プログラミングパラダイム(事象)の度合いを **主観で決めている、という点で苦手** ですが、

「非エンジニアにもわかりやすく理解をしてもらうため」に **特徴の俯瞰をしている、という点** では好きです。

　

さて、突然ですが、私は **Ruby** と **TypeScript** が好きです。
(実はTypeScriptについては、始めるまでは良い印象を持っていませんでしたが。)

では、私は **どのようなプログラムの見方** 、つまり、
**どのようなプログラミングパラダイムを好んでいる** のでしょうか？

残念ながら、 **適切なプログラミングパラダイムを示す単語はなさそう** でした。

**なければ、作って、説明しよう**
というのが、本ポエムの動機です。

:::note warn
本記事はポエムです。
本記事はオブジェクト指向プログラミング(OOP) の知識/経験を前提とします。
また、構造型指向(SOP)や、公称型指向(NOP)は、 本ポエム内の造語であり、一般的な単語ではありません。
:::

# 構造型指向(SOP) と 公称型指向(NOP)

**構造型指向プログラミング** (**SOP**) : **S**tructural typing **O**riented **P**rogramming
**公称型指向プログラミング** (**NOP**) : **N**ominal typing **O**riented **P**rogramming

まずは、これらの定義を説明します。

**Nominal typing** は、聞きなれないという人も多いでしょう。
実は筆者も、そうでした。筆者は、**[Nominal typing | TypeScript Deep Diveの日本語版](https://typescript-jp.gitbook.io/deep-dive/main-1/nominaltyping)** を読んで初めて意識しました。

**Nominal typing** を **公称型** として **@suin** さんが関連した、分かりやすい記事を書いてくれています。
**Nominal typing** を聞いたことがない人は、まずは、こちらの記事をよんでください。

https://qiita.com/suin/items/52cf80021361168f6b0e

https://qiita.com/suin/items/57cfc0ec9bb1a6995aa5

なお、 **英語版wikipedia** には、 **nominal type system** の記事があります。

https://en.wikipedia.org/wiki/Nominal_type_system

> nominal or nominative type system (or name-based type system)

**名前ベースの型システム** とも言えますが、本記事では、 **公称型** で統一します。
これは、継承などで型同士の関係が明示的に定義されることを前提とした型システムと言えるでしょう。

> Nominal type systems contrast with [structural type systems](https://en.wikipedia.org/wiki/Structural_type_system), 

また、記事中には、対比として **structural type system** の記事へのリンクがあります。

https://en.wikipedia.org/wiki/Structural_type_system

> structural type system (or property-based type system)

**プロパティ(属性)ベースの型システム** とも言えますが、本記事では、 **構造型** で統一します。
これは、型の構造(属性の構成)に着目した型システムと言えるでしょう。


つまり、本記事中では

**型の構造(属性の構成)** に着目する手法を、 **構造型指向(SOP)**
 **(継承など)定義された関係** に着目する手法を、 **公称型指向(NOP)**

とします。


# subtyping ≒ (型の)互換性

さて、TypeScriptの普及でよく耳にするようになった、
**structural subtyping** (構造的部分型) という単語の
**subtyping とはなんでしょうか？**

~~筆者は英語に疎いのですが、~~
**typing "型付け"** が、 **type "型"** の動名詞であるように、
**subtypingは、subtypeの動名詞** でしょう。
(typing は、 dynamic typing(動的型付け) や、 static typing(静的型付け) などで使われています。)

では、次に**名詞 の subtype** について考えてみます。
**subtypes** は、 [**weblio**で調べる](https://ejje.weblio.jp/content/subtypes) と、ライフサイエンス辞書において、

> サブタイプ, 亜型, 亜類型

という意味が掲載されています。もともとは、生物学における分類のための単語と考えられます。

サブタイプを [**コトバンク**で調べる](https://kotobank.jp/word/%E3%82%B5%E3%83%96%E3%82%BF%E3%82%A4%E3%83%97-683664) と栄養・生化学辞典において、

> 特定の機能をもつ分子（ホルモンレセプターなど）を，性質に従っていくつかの型に分類する場合，さらにいくつかの項目について細分することがある．**この細分されたそれぞれの型．**

という説明が記載されています。
筆者は、一般的なサブタイプの認識としては、この説明が分かりやすいと感じました。

では、プログラミングにおける **subtype** はどうでしょうか？

プログラミングにおいては、 **subtype** は、 **派生型** や **部分型** と訳されます。
**派生型**  と **部分型** は同一のものを指していると考えて問題ない[^1]ですが、
与える印象は異なります。

[^1]: 筆者は、**部分型** から、属性数の少ない親クラスを誤って連想してしまうため、**部分型** は常に脳内で **派生型** に変換しています。

例えば OOPでは、以下の様に使い分けられているようにも感じます。

**派生型** : **extend(継承)** を利用するとき
**部分型** : **ポリモーフィズム(多態性)** を利用するとき

これは、 **subtype** が、プログラミングにおいて、
**実装の再利用** 時と、 **型の分類** 時の2つのシーンで使われるためです。

**subtyping** は、後者、型の分類時のシーンでよく使われているように感じます。
そのため、本記事での、 **subtyping** は **(型の)互換性** と解釈します。
(ただし、structural subtyping については、 **慣例として構造的部分型** とします。)

なお、筆者は **subtyping** に関連したキーワードとして、
**Cast , Interface , Type assetion** 等の単語を連想します。
これらのキーワードの方が、プログラミングに直接関連しているため、
馴染みやすい人も多いでしょう。

なお、subtype について、**実装の再利用** と **型の分類** を **区別して考えることは重要** です。
本記事の、SOP/NOP については、後者 **型の分類** のみが議論の対象となります。

![subtyping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352865/557eb00a-a42b-d2df-788b-148749ce3ff0.png)


なお、以下のように、type/typing を使う場合と、 subtyping を使う場合があります。

　- structural type(構造型)
　- structural type system(構造型システム)
　- structural typing(構造的型付け)
　- structural subtyping(構造的部分型)

本記事中では、個々のプログラミング言語など具体的な場合は、より明確な subtyping を、
指向(oriented) 、設計や考え方など抽象的な場合は、 type/typing を使用しますが、
**使い分けに重要な意味はありません** 。


# ダックタイピング(duck typing) について

**構造的部分型** (structural subtyping) に似た概念として、
**ダックタイピング**(duck typing) があります。

> **ある鳥が鴨のように見え、鴨のように泳ぎ、鴨のように鳴くならば、それはたぶん鴨である。**[^2]

[^2]: https://ja.m.wikipedia.org/wiki/%E3%83%80%E3%83%83%E3%82%AF%E3%83%BB%E3%83%86%E3%82%B9%E3%83%88

ダックタイピングは、上記引用で説明される、ダック・テスト(duck test)に由来します。

> 特定のメソッド（またはメソッド群）を実装したオブジェクトが必要な場合に、与えられたオブジェクトが必要とする **メソッドのすべてを実装しているのであれば** 、その実装方法がどのようなものであれ（型宣言の有無、継承の経路などに関係なく）、 **それで良い** という考え方である。[^2]

**『メソッドの実装』** は、 **プロパティ(属性)の有無** と **同じ意味** であり、
**『それで良い』** は、 **互換性がある** と **同じ意味** と解釈できます。

では、 **構造的部分型** と **ダックタイピング** は同じものなのでしょうか？

かの matz も ５年前につぶやいているようです。

https://twitter.com/yukihiro_matz/status/773890081144778752

では、その謎を解き明かすべく、英語版wikipediaのgoogle翻訳結果を参照してみましょう。

> ダックタイピングは、構造型タイピングと似ていますが、異なります。 **構造型は静的型付けシステム** であり、型の構造によって型の互換性と同等性を判断しますが、 **ダックタイピングは動的** であり、実行時にアクセスされる型の構造の部分のみによって型の互換性を判断します。[^3]

[^3]: https://en.wikipedia.org/wiki/Duck_typing

つまり、プロパティ（属性）で互換性判定を行う点では同じだが、以下の様に区別されるようです。

 - **静的型付け** 、つまり、 **コンパイル時** の互換性判定が、 **構造的部分型**
 - **動的型付け** 、つまり、 **実行時での互換性判定** が、 **ダックタイピング**

しかしながら、筆者はこの分け方に、 **完全には賛同しかねます** 。

なぜなら、ダックタイピング由来の、ダックテストの語感からは、
公称型（アヒルの判定を、遺伝子などの分析で分類するイメージ）に対する、
構造型（アヒルの判定を、外見や振る舞いで分類するイメージ）の特徴を連想し、
そこに、 **静的型付け か 動的型付け かどうかの意味合いは存在しない** ためです。
(ダックタイピングの「振る舞い」という単語から、少しだけ動的型付けを連想しますが。)

ダックタイピングに、動的型付け か 静的型付け かの意味合いが含まれるように感じるのは、
当初の議論において比較対象となりやすい **主流の** プログラミング言語 が、
「**静的型付け** 、かつ、 **公称型の互換性判定**」のプログラミング言語と
「**動的型付け** 、かつ、 **構造型の互換性判定**」のプログラミング言語、
の2種類[^4] だったことも一因でしょう。
（また、それに伴い、ダックタイピングに、動的型付けのネガティブな特徴のイメージも[^5]付随したため、それを避けるために、構造的部分型を用いることも多いと感じています。）

[^4]: ここでは、C, Java に対する、python, php ruby を想定
[^5]: 例えば、typoしても動く(実行時にしか気づかない）など

実際に、 **[TypeScript Deep Dive 日本語版](https://typescript-jp.gitbook.io/deep-dive/getting-started/why-typescript#nastructural-type-system)** では、**構造的な型(Structural type system)** に対する説明として、以下の様に記載されています。

> TypeScriptは、JavaScript 開発者に対する認知的な負荷をなるべく小さくするため、 **構造的な型(structural type)** を採用しています。これが意味することは、 **ダックタイピング(duck typing)が第一級(言語レベルでサポートされている)のもの** である、ということです。

この記述からは、 **構造的部分型がダックタイピングの派生** であり、
**ダックタイピングは構造的部分型を含むもの** であるように読み取れます。

この例の他にも、例えば、静的型付け言語である、 go で ダックタイピング の記事を調べると、
ダックタイピングに対しての解釈が異なる記事を、たくさん見つけることができるでしょう。

以上より、筆者の見解としては、**ダックタイピング** と **構造的部分型** は、
**広義では同じ** だが、 **狭義では異なる** と考えています。

![ダックタイピングと公称的部分型.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352865/2d9c8d82-b4d5-57eb-6c9b-14eb9a42d66f.png)

# つづく

~~語りまで入れませんでしたが~~ つづきは、**[「シコウ」を語る Advent Calendar 2021](https://qiita.com/advent-calendar/2021/shikou_poem)** 22日目の記事として、**構造型指向(SOP) か 公称型指向(NOP) か、それを知りたい ~ 型と設計 ~** を投稿予定です。[^6]

**[「シコウ」を語る Advent Calendar 2021](https://qiita.com/advent-calendar/2021/shikou_poem)** は、~~ほとんど埋まっていない~~ まだまだ枠がありますので、語りたいことがある人は、是非参加してください！

[^6]: 実はずいぶん前の書きかけの記事の供養で、この続きは投稿できるレベルの内容が書けていませんでした。22日までに頑張って書こうと思います。