ようやく仕事が自分のペースで進められるようになってきた。メンターとの 1on1 で趣味がない、俺達には仕事しかない、そしてそれは持続可能性がない、という最悪の話題で盛り上がる。
- https://open.spotify.com/intl-ja/track/4WpNdRhrQHk9M54UIjL7HF?si=981e0de59c754612
- 良い(´;ω;`) 結局こういう半音で上がったり下がったりするのが激刺さりしちゃう、マジ骨の髄まで日本人
- Duck Typing
- ダックタイピングって結局なんなのかよく分かってない。Python・JS・Ruby みたいな動的型付言語の挙動について表現するときに使われたり、構造的部分型を説明するときに使われたり、Go の
interfaceについて説明するときに使われたりしている。結局何を指してるのか分からない。- 「ある言語において、複数の構造体(or クラス)が同じメソッドを実装しているとき、それらが暗黙的に相互に交換可能となる挙動」ぐらいの意味っぽい。
- 一般的な動的型付言語は何も特別な操作をせずとも自ずとそうなる。つまり、ある関数があるメソッドを持つオブジェクトを引数に取るとき、その関数には同じ名前のメソッドさえ持っていればどんな形状のオブジェクトも渡せて、正常に動作することが期待できる。動的型付言語では、この挙動があるから複数の型の異なるオブジェクトを統一的な仕組みで扱うことができる。
- 一般的に狭義のダックタイピングはこういう動的型付言語の挙動を指すっぽい。
- 「暗黙的」というのがダックタイピングという用語を理解するのに重要なポイントだ。静的型付言語の世界観でいうと、それは関数の引数として渡される複数のオブジェクトが「暗黙的に」同じスーパータイプを継承している状況。
- 一般的な動的型付言語は何も特別な操作をせずとも自ずとそうなる。つまり、ある関数があるメソッドを持つオブジェクトを引数に取るとき、その関数には同じ名前のメソッドさえ持っていればどんな形状のオブジェクトも渡せて、正常に動作することが期待できる。動的型付言語では、この挙動があるから複数の型の異なるオブジェクトを統一的な仕組みで扱うことができる。
- Java のようにある型が「明示的に」何を継承してるか、何を実装してるかを示す必要がある言語では異なる抽象化の方法が必要になる。
- Java の型システムは階層的だ。スーパータイプ(親)を任意のサブタイプ(子)で置き換えることができる。また、スーパータイプを受け取る関数は、スーパータイプを継承した複数のサブタイプを受け付けることができる。これによってポリモーフィズム(サブタイプ多相)が可能になる。つまり、Java ではクラスの継承関係を利用した抽象化がなされている。
- では Go ではどうか。 Go の
structは親子関係に相当するものを表現できない(埋め込みはあるけど継承じゃない)ので、Java とは異なる方法で複数の型を抽象化する必要がある。- ここで
interfaceが登場する。つまり、interface は階層的な型システムを持たない Go でサブタイプ多相を実現するために導入された機構だ。これは基本的に Java のインターフェースと役割は同じだが、ひとつ異なるのは、明示的に関係性を指定することなく、そのinterfaceと同じメソッドを持つ構造体が暗黙的にそれを実装したことになるということだ。 これは確かに(狭義のダックタイピングとは異なるものの)ダックタイピング的ではある。- ここでインターフェースはそれを実装する型と暗黙的なスーパータイプ<->サブタイプの関係を持つことになる。これが Go でほぼ唯一の親子関係。
- このような、構造が一致してることによってサブタイプが暗黙的に発生するとき、それを構造的部分型と呼ぶ(TypeScript も構造的部分型があるよね)。つまり、Go の場合は、
interfaceというダックタイピング的機構によって、interfaceと構造体の間に構造的部分型の関係が成り立つことになる。
- ここで
- 「ある言語において、複数の構造体(or クラス)が同じメソッドを実装しているとき、それらが暗黙的に相互に交換可能となる挙動」ぐらいの意味っぽい。
- ダックタイピングって結局なんなのかよく分かってない。Python・JS・Ruby みたいな動的型付言語の挙動について表現するときに使われたり、構造的部分型を説明するときに使われたり、Go の