過去スレ
オブジェクト指向はオワコン (2023/08/26〜)
https://mevius.5ch.io/test/read.cgi/tech/1721393540/
オブジェクト指向はオワコン? (2024/07/19〜)
https://mevius.5ch.io/test/read.cgi/tech/1721393540/
オブジェクト指向はオワコン? part2 (2026/08/13〜)
https://mevius.5ch.io/test/read.cgi/tech/1786599483/
オブジェクト指向はオワコン? part3 (2026/08/26〜)
https://mevius.5ch.io/test/read.cgi/tech/1787712923/
オブジェクト指向はオワコン? part4
1デフォルトの名無しさん
2026/09/24(木) 21:48:24.69ID:R0E4hCxI2026/09/25(金) 14:15:10.04ID:re2WXZGd
>>前スレ終盤
あんなものは抽象化じゃねぇってw
抽象という言葉の意味すら理解していない無知がカッコつけてそう呼んでいるだけ。
あえていえば相称関数あるいはデータ構造付属メソッド
あんなものは抽象化じゃねぇってw
抽象という言葉の意味すら理解していない無知がカッコつけてそう呼んでいるだけ。
あえていえば相称関数あるいはデータ構造付属メソッド
2026/09/25(金) 14:26:17.33ID:h51z3iXb
抽象データ型(ちゅうしょうデータがた、英: abstract data type、ADT)とは、データ構造とその操作手続きを定義したデータ型、またはデータ抽象の方法の1つ。
通常のデータ型であれば変数宣言で変数に束縛されるものは値であるが、抽象データ型の世界において値に相当するものはデータ構造とその操作のまとまりである。
抽象データ型を用いない場合、データ構造またはデータの操作手続きのアルゴリズムの変更を行うとソースコード中にその変更部分が散在してしまい規模によっては修正困難となるが、データとその操作がひとまとめに記載されることになる抽象データ型においては、型の定義における実装部分を変更するだけで修正が完了する。
通常のデータ型であれば変数宣言で変数に束縛されるものは値であるが、抽象データ型の世界において値に相当するものはデータ構造とその操作のまとまりである。
抽象データ型を用いない場合、データ構造またはデータの操作手続きのアルゴリズムの変更を行うとソースコード中にその変更部分が散在してしまい規模によっては修正困難となるが、データとその操作がひとまとめに記載されることになる抽象データ型においては、型の定義における実装部分を変更するだけで修正が完了する。
2026/09/25(金) 14:26:49.36ID:h51z3iXb
プログラムが実装されたとき、抽象データ型は実装を隠蔽するインタフェースを表す。
実装は将来において変更されうるので、抽象データ型のユーザーは実装ではなくインタフェースに関心がある。
抽象データ型の強みはユーザーから実装が隠蔽されていることである。
インタフェースのみが公開されるのである。
このことは、抽象データ型がいろいろな方法で実装されうることを意味するが、インタフェースに忠実な限りユーザープログラムは影響を受けないのである。
実装は将来において変更されうるので、抽象データ型のユーザーは実装ではなくインタフェースに関心がある。
抽象データ型の強みはユーザーから実装が隠蔽されていることである。
インタフェースのみが公開されるのである。
このことは、抽象データ型がいろいろな方法で実装されうることを意味するが、インタフェースに忠実な限りユーザープログラムは影響を受けないのである。
2026/09/25(金) 14:32:18.06ID:h51z3iXb
抽象データ型は各自のプログラムで必要となる固有のものを各自で定義できる。
汎用的な抽象データ型としては、以下のようなものがライブラリとして提供されていることが多い。
Collection
Container
List
String
Set
Multiset
Map
Multimap
Graph
Tree
Stack
Queue
など
汎用的な抽象データ型としては、以下のようなものがライブラリとして提供されていることが多い。
Collection
Container
List
String
Set
Multiset
Map
Multimap
Graph
Tree
Stack
Queue
など
2026/09/25(金) 14:35:34.10ID:re2WXZGd
>>3,4
その辺の入門的なWebから引用してきたような説明だな
その辺の入門的なWebから引用してきたような説明だな
2026/09/25(金) 14:38:36.88ID:re2WXZGd
しかし、特に抽象的でないものに対して抽象,抽象
うるせえ野郎だな
中小くらいにしとけ
うるせえ野郎だな
中小くらいにしとけ
2026/09/25(金) 14:43:09.86ID:OKDl5iMv
オブジェクト指向におけるインタフェース抽象型はその抽象データ型をさらに発展させたもの
複数の異なる型に対して共通の振る舞いをインタフェースとして宣言する
そして各型はそのインタフェースを実装する
プログラムの引数や変数などをインタフェース抽象型として記述できることが特徴である
それによって共通の振る舞いを一つのコードで共通コード化できる
そのインタフェースを実装しているならば任意な型で動作することができる
つまり特定の型に依存せずに抽象的なコードを書くことができるようになった
複数の異なる型に対して共通の振る舞いをインタフェースとして宣言する
そして各型はそのインタフェースを実装する
プログラムの引数や変数などをインタフェース抽象型として記述できることが特徴である
それによって共通の振る舞いを一つのコードで共通コード化できる
そのインタフェースを実装しているならば任意な型で動作することができる
つまり特定の型に依存せずに抽象的なコードを書くことができるようになった
2026/09/25(金) 14:46:53.55ID:re2WXZGd
異なるデータ構造に対する処理で
同じメソッド名、引数で呼べる関数があったら
なぜ抽象なのか
同じメソッド名、引数で呼べる関数があったら
なぜ抽象なのか
2026/09/25(金) 14:56:02.05ID:UuV8E4i+
型は違えど同じ共通操作をしたいことがプログラミングでは多々あるだろ
それを共通インタフェースとして宣言して各型はそのインタフェースを実装する
そのインタフェース抽象型で記述した関数は抽象的なコードになって各型に横断的に使える
これは抽象的なジェネリックな関数のパラメータ型が、あるインタフェース実装をしている制約を満たす時と同じになる
それを共通インタフェースとして宣言して各型はそのインタフェースを実装する
そのインタフェース抽象型で記述した関数は抽象的なコードになって各型に横断的に使える
これは抽象的なジェネリックな関数のパラメータ型が、あるインタフェース実装をしている制約を満たす時と同じになる
11デフォルトの名無しさん
2026/09/25(金) 14:57:44.90ID:DP8L+qwL >>9
具体的データ構造に依存しないから抽象ではあるんじゃね
その抽象が役立つものかどうかは別として抽象ではある
仮にその抽象にモスフングスという名前をつけてみよう
その名前が役立つかどうかは別の話だ
具体的データ構造に依存しないから抽象ではあるんじゃね
その抽象が役立つものかどうかは別として抽象ではある
仮にその抽象にモスフングスという名前をつけてみよう
その名前が役立つかどうかは別の話だ
2026/09/25(金) 15:04:45.24ID:b8yGhIZZ
>>9
それだけだとたまたま構造的に同じメソッド名だけかもしれない
構造的なインタフェース型付けではそれでも同じに扱ってしまう弱点がある
一方でインタフェース名を宣言する場合は区別ができてたまたま同じメソッド名と同じ方の引数であってもどのインタフェース名を実装している型はどうかで区別できる
つまりインタフェース抽象型はたまたま同じを確実に排除できる
それだけだとたまたま構造的に同じメソッド名だけかもしれない
構造的なインタフェース型付けではそれでも同じに扱ってしまう弱点がある
一方でインタフェース名を宣言する場合は区別ができてたまたま同じメソッド名と同じ方の引数であってもどのインタフェース名を実装している型はどうかで区別できる
つまりインタフェース抽象型はたまたま同じを確実に排除できる
2026/09/25(金) 15:16:55.58ID:7GEWmO3W
話は簡単だよ
抽象型を用いずに関数を書くと各々の型ごとに別々の関数を書かなきゃいけない
手間もかかるしほぼ同じ関数が何度も出てきて可読性も悪いし保守性も悪い
よーするに抽象型を使った関数は良いコード
抽象型を用いずに関数を書くと各々の型ごとに別々の関数を書かなきゃいけない
手間もかかるしほぼ同じ関数が何度も出てきて可読性も悪いし保守性も悪い
よーするに抽象型を使った関数は良いコード
2026/09/25(金) 15:24:32.24ID:y3X2IqCa
>>12
それは名前的型システムと構造的型システムの違いの話であって、インターフェイス抽象型という概念はそのいずれとも結び付くのだから、最後の「インターフェイス抽象型は……できる」というのは論旨がつながらないと思うけど。
名前的型付けによるインターフェイス抽象型は……ということだよね。
それは名前的型システムと構造的型システムの違いの話であって、インターフェイス抽象型という概念はそのいずれとも結び付くのだから、最後の「インターフェイス抽象型は……できる」というのは論旨がつながらないと思うけど。
名前的型付けによるインターフェイス抽象型は……ということだよね。
2026/09/25(金) 15:47:43.22ID:re2WXZGd
2026/09/25(金) 16:26:19.05ID:Dh2BjwsM
抽象型(abstract type)とはプログラミングの型システムのうち、名前的型システムにおける型の一種であり、直接インスタンス化することができないという特徴を持つ。
対義語は具象型または具体型(concrete type)であり、具象型はインスタンス化することができる。
抽象型は実装を提供しないか、あるいは不完全な実装を提供する。
具体的な形態や仕様はプログラミング言語ごとに異なるが、いくつかの言語において、実装を持たない抽象型はインタフェースやプロトコルヤトレイト等と呼ばれている。
クラスを持つプログラミング言語では、抽象型は抽象クラスとして実装される場合があり、具象型は具象クラスとして実装される。
ただし抽象クラスはインスタンス用の変数を持つことができる場合があり、それを持たないインターフェイス等と比べると別の機能が付加されている。
対義語は具象型または具体型(concrete type)であり、具象型はインスタンス化することができる。
抽象型は実装を提供しないか、あるいは不完全な実装を提供する。
具体的な形態や仕様はプログラミング言語ごとに異なるが、いくつかの言語において、実装を持たない抽象型はインタフェースやプロトコルヤトレイト等と呼ばれている。
クラスを持つプログラミング言語では、抽象型は抽象クラスとして実装される場合があり、具象型は具象クラスとして実装される。
ただし抽象クラスはインスタンス用の変数を持つことができる場合があり、それを持たないインターフェイス等と比べると別の機能が付加されている。
2026/09/25(金) 16:59:04.15ID:y3X2IqCa
抽象型という概念が、名前的型システムとしか結び付かないということは別にないと思うんだが……。
2026/09/25(金) 17:12:39.50ID:bJ1E9BNt
構造的型システムは問題点が山積みだかららしい
構造が同じだと同一視するから事故が起きまくり
例えばこんな例もあるようだ
https://scrapbox.io/nishio/%E5%90%8D%E5%89%8D%E7%9A%84%E5%9E%8B%E3%81%A8%E6%A7%8B%E9%80%A0%E7%9A%84%E5%9E%8B%E3%81%AE%E5%8B%98%E9%81%95%E3%81%84%E3%81%AB%E3%82%88%E3%82%8B%E5%AE%9F%E8%A9%B1
構造が同じだと同一視するから事故が起きまくり
例えばこんな例もあるようだ
https://scrapbox.io/nishio/%E5%90%8D%E5%89%8D%E7%9A%84%E5%9E%8B%E3%81%A8%E6%A7%8B%E9%80%A0%E7%9A%84%E5%9E%8B%E3%81%AE%E5%8B%98%E9%81%95%E3%81%84%E3%81%AB%E3%82%88%E3%82%8B%E5%AE%9F%E8%A9%B1
2026/09/25(金) 17:41:09.60ID:H+jZbV0f
>>18
それはGoだと発生しないね
それはGoだと発生しないね
2026/09/25(金) 18:11:54.83ID:Jn2tRD0t
>>19
どのような仕組みで防いでいるの?
どのような仕組みで防いでいるの?
21デフォルトの名無しさん
2026/09/25(金) 18:52:21.84ID:DP8L+qwL >>19
Javaでも起きないよ(小声
Javaでも起きないよ(小声
22デフォルトの名無しさん
2026/09/25(金) 20:22:56.67ID:DolTsCFZ >>18
OCamlだと名前的型と構造的型の使い分けができるみたい。
OCamlだと名前的型と構造的型の使い分けができるみたい。
23デフォルトの名無しさん
2026/09/25(金) 21:14:30.62ID:r8ffWfv+ 多重継承は?
2026/09/25(金) 21:22:17.71ID:k/tTX8EV
静的型付けがなぜ重視されるのか?
それは型が異なるものが間違って使われることを100%防げるため
人間はミスや混乱するものだからコンパイル時点で100%防げることは大きい
名前的インターフェイスによる抽象型の型付けも同様
その名前のインターフェイスが実装されている型だけを受け入れる
間違いを100%防ぐことができる
一方で構造的な場合はどうか?
100%防ぐことは絶対にできない
それは型が異なるものが間違って使われることを100%防げるため
人間はミスや混乱するものだからコンパイル時点で100%防げることは大きい
名前的インターフェイスによる抽象型の型付けも同様
その名前のインターフェイスが実装されている型だけを受け入れる
間違いを100%防ぐことができる
一方で構造的な場合はどうか?
100%防ぐことは絶対にできない
25デフォルトの名無しさん
2026/09/25(金) 21:47:20.00ID:DP8L+qwL >>24
実装するインターフェイスを間違える可能性だってあるでしょうが!!
実装するインターフェイスを間違える可能性だってあるでしょうが!!
2026/09/25(金) 22:15:25.30ID:/pRvmlos
インターフェイス毎に別の名前が付いてるから大丈夫やろ
インターフェイス毎に実装すべきメソッド一覧も異なるからそこでも気付く
インターフェイス毎に実装すべきメソッド一覧も異なるからそこでも気付く
27デフォルトの名無しさん
2026/09/25(金) 22:51:22.35ID:DP8L+qwL そんなガバガバな理由で100%防げるなら関数名や変数名で構造的型付けの問題も100%防げるんちゃう?
2026/09/25(金) 23:18:11.64ID:jN1iKnwt
構造的型付けは利用する複数のライブラリと自作の間で入り乱れたら詰むよな
インターフェースに名前があれば万が一でも別名指定もできるから確実に安心だ
インターフェースに名前があれば万が一でも別名指定もできるから確実に安心だ
2026/09/25(金) 23:21:53.97ID:YdShWX+l
ガバガバおじさんw
2026/09/25(金) 23:56:08.55ID:1Z1witsl
2026/09/26(土) 00:06:52.80ID:GiN3WV5L
>>30
C++やTypeScriptは名前なしでも構造が一致すれば使えるぞ
C++やTypeScriptは名前なしでも構造が一致すれば使えるぞ
2026/09/26(土) 00:28:34.21ID:hH8wyUky
2026/09/26(土) 00:37:34.99ID:eketQAju
Pythonは名前的型システムをベースにしつつ、特定の属性を持つことを「◯◯プロトコル」と呼んで構造的型システムの要素を加味していたりするし、両者の組み合わせというアプローチもあると思うな。
2026/09/26(土) 04:18:52.46ID:QMw9T6l2
抽象型には名前があるべきだ
名前があると可読性が格段に良くなりコンパイラによるエラーもわかりやすくなる
名前のない構造的な抽象型はデメリットが多すぎる
名前があると可読性が格段に良くなりコンパイラによるエラーもわかりやすくなる
名前のない構造的な抽象型はデメリットが多すぎる
2026/09/26(土) 09:20:43.98ID:hp4h2mNt
名前のない抽象型ってどんなの?
見たことないんだけどどんなコードのこと?
見たことないんだけどどんなコードのこと?
36デフォルトの名無しさん
2026/09/26(土) 09:25:49.44ID:7QoscKFO ケースバイケースで判断したらええ
どちらでも良いことをこちらじゃないとダメだと
思い込むのはアスペ仕草でしかないぞ
どちらでも良いことをこちらじゃないとダメだと
思い込むのはアスペ仕草でしかないぞ
2026/09/26(土) 09:56:18.66ID:RhIbEw/H
たとえばPythonでは__next__属性と__iter__属性を持つオブジェクトはイテレーターとされるけど、構造的型付けの一種とみて良いんじゃない? iteratorプロトコルと称されるけど、iteratorという名前をコード上に書くわけではない。
名前的型システム+継承によるサブタイピング多相だけで全てを賄おうとすると継承ツリーが巨大になって管理困難になるということで、いろいろなアプローチが試みられているところだと思うけど。
名前的型システム+継承によるサブタイピング多相だけで全てを賄おうとすると継承ツリーが巨大になって管理困難になるということで、いろいろなアプローチが試みられているところだと思うけど。
2026/09/26(土) 10:48:28.81ID:FcRls3mc
>>34さんはダックタイピング、ジェネリックプログラミング/テンプレートプログラミングに対してどこか独特な善し悪しの境界線を持っていそうだね
2026/09/26(土) 11:02:26.73ID:hp4h2mNt
>>37
それはduck typingだね
duck typingをstructural typingの一種と見て良いんじゃないかということだけど区別したほうがいいんじゃない?
特にこういう議論においては
それはduck typingだね
duck typingをstructural typingの一種と見て良いんじゃないかということだけど区別したほうがいいんじゃない?
特にこういう議論においては
2026/09/26(土) 11:43:19.70ID:YrlTBNaA
2026/09/26(土) 12:11:27.38ID:aDxlc5/o
>>39
構造的型付けという概念は、静的型付けとも動的型付けとも結び付く概念だから、ダックタイピングを構造的型付けの1種とみなすことに問題があるとは思わないが。
ま、37は>>35に対する1つの考え方として提示したものだから、35自身がたとえば静的型付けしか念頭に置いてなかったということであれば、その期待に沿うものでなかったということなんだろうけど。
>>40
インターフェイスも継承によるサブタイピング多相に他ならない。継承ツリーが大きくなるというのは、たとえばPythonで現在◯◯プロトコルとして実現されているところを全て明示的な抽象基底クラスの継承を必要とするようにすることもできなくはないけれども、そうするとその分、プロトコル的アプローチでは必要とされない継承が増えてしまうということね。むろん得失はあるから、プロトコルのような構造的型付け的なアプローチの方が優れているというわけでは必ずしもないけれども、抽象クラスなりインターフェイスなりから継承してサブタイピング多相をやっておけば万事解決というほど簡単なことではなさそうだという認識がある程度共有されているからこそ、現在、構造的型付けのようなアプローチが模索されているということだと思うよ。
構造的型付けという概念は、静的型付けとも動的型付けとも結び付く概念だから、ダックタイピングを構造的型付けの1種とみなすことに問題があるとは思わないが。
ま、37は>>35に対する1つの考え方として提示したものだから、35自身がたとえば静的型付けしか念頭に置いてなかったということであれば、その期待に沿うものでなかったということなんだろうけど。
>>40
インターフェイスも継承によるサブタイピング多相に他ならない。継承ツリーが大きくなるというのは、たとえばPythonで現在◯◯プロトコルとして実現されているところを全て明示的な抽象基底クラスの継承を必要とするようにすることもできなくはないけれども、そうするとその分、プロトコル的アプローチでは必要とされない継承が増えてしまうということね。むろん得失はあるから、プロトコルのような構造的型付け的なアプローチの方が優れているというわけでは必ずしもないけれども、抽象クラスなりインターフェイスなりから継承してサブタイピング多相をやっておけば万事解決というほど簡単なことではなさそうだという認識がある程度共有されているからこそ、現在、構造的型付けのようなアプローチが模索されているということだと思うよ。
2026/09/26(土) 12:22:15.08ID:WpxzvFPy
2026/09/26(土) 12:45:18.77ID:aDxlc5/o
Java等でいうインターフェイスの実装というのは、C++でいう抽象クラスからの継承に概ね相当する概念であって、インターフェイスは継承ツリーを作らないというのは単なるレトリックでしょ。C++で継承といっていたものを、用語上「継承」と「(インターフェイスの)実装」等に分けただけ。
本質的なのは、サブタイピング多相を実現するのに明示的なクラス名(インターフェイス名)の指定を必要とするという点なんだけど。
本質的なのは、サブタイピング多相を実現するのに明示的なクラス名(インターフェイス名)の指定を必要とするという点なんだけど。
2026/09/26(土) 12:53:08.95ID:NqaKT3Js
>>43
それあんた逆だよ
C++はインターフェースがない不完全な言語だから抽象クラスで代用して禁断の多重継承を許している
Javaはインターフェースがある正しい言語だから多重継承は禁止されていてインターフェースをいくつでも好きなだけ実装できる
それあんた逆だよ
C++はインターフェースがない不完全な言語だから抽象クラスで代用して禁断の多重継承を許している
Javaはインターフェースがある正しい言語だから多重継承は禁止されていてインターフェースをいくつでも好きなだけ実装できる
45デフォルトの名無しさん
2026/09/26(土) 13:10:49.97ID:cJdAZEFI >>44
時系列的におかしいような。
時系列的におかしいような。
2026/09/26(土) 13:14:02.37ID:NqaKT3Js
47デフォルトの名無しさん
2026/09/26(土) 13:14:02.91ID:7QoscKFO Javaのようなinterface方式はクラスを修正してinterfaceを実装しないといけないから修正不可能なクラスの共通処理を実装できないのがネックだな
2026/09/26(土) 13:23:51.97ID:NqaKT3Js
49デフォルトの名無しさん
2026/09/26(土) 13:24:48.01ID:7QoscKFO >>48
たとえばどういうのよ?
たとえばどういうのよ?
2026/09/26(土) 14:28:05.74ID:cJdAZEFI
>>46
Modula-3のinterfaceがあって、c++ではhpp/cppと純粋仮想関数によってのちのjava系interfaceの
ようなことはできている。
javaは多重継承を禁止する必要性から、c++で可能だった機能をinterfaceキーワードにまとめた。
このへんは、大きなクラスをつくれないようにする分出公理のやりかたに似ている(個人的感想です)。
c++の時点では、不完全というより、精錬されていないという感じ。
Modula-3のinterfaceがあって、c++ではhpp/cppと純粋仮想関数によってのちのjava系interfaceの
ようなことはできている。
javaは多重継承を禁止する必要性から、c++で可能だった機能をinterfaceキーワードにまとめた。
このへんは、大きなクラスをつくれないようにする分出公理のやりかたに似ている(個人的感想です)。
c++の時点では、不完全というより、精錬されていないという感じ。
2026/09/26(土) 14:46:21.41ID:cJdAZEFI
公理的プログラミング言語を考えると、そのひとつとしてクライスリトリプルであること。
モナド系であれば、純粋モナドである必要はないがモナド則に反しないこと。
これは圏論的プログラミングであり、オブジェクト指向のメッセージングを「射」と考えれば、
オブジェクト指向プログラミング=圏論的プログラミングだ。
モナド系であれば、純粋モナドである必要はないがモナド則に反しないこと。
これは圏論的プログラミングであり、オブジェクト指向のメッセージングを「射」と考えれば、
オブジェクト指向プログラミング=圏論的プログラミングだ。
2026/09/26(土) 14:50:49.93ID:RO16A3on
>>50
多重継承は問題点が多すぎるため、クラス継承は一つに限る、つまり多重継承禁止がスタンダードになった
親クラスとその子クラスは『1対多』になる
インターフェースは対極的な位置付けで、各機能毎にインターフェースをいくつも実装する
インターフェースとそれを実装するクラスは『多対多』
ある1つのクラスから見ると『多対1』になる
多重継承は問題点が多すぎるため、クラス継承は一つに限る、つまり多重継承禁止がスタンダードになった
親クラスとその子クラスは『1対多』になる
インターフェースは対極的な位置付けで、各機能毎にインターフェースをいくつも実装する
インターフェースとそれを実装するクラスは『多対多』
ある1つのクラスから見ると『多対1』になる
2026/09/26(土) 15:00:14.63ID:ejaIPLOy
2026/09/26(土) 15:06:24.48ID:ejaIPLOy
複おじはいつも原因と結果がごちゃ混ぜなんだよな
巨大な継承ツリーを作らないように設計してるから巨大な継承ツリーにならないというだけで
クラスだからとかインターフェースだからという話じゃ全然ない
Pythonはクラスの多重継承をサポートしてるわけだけど
クラスを使っても巨大な継承ツリーを作らないように設計すれば巨大な継承ツリーにならない
当たり前だな
巨大な継承ツリーを作らないように設計してるから巨大な継承ツリーにならないというだけで
クラスだからとかインターフェースだからという話じゃ全然ない
Pythonはクラスの多重継承をサポートしてるわけだけど
クラスを使っても巨大な継承ツリーを作らないように設計すれば巨大な継承ツリーにならない
当たり前だな
2026/09/26(土) 15:29:24.47ID:kJvzFJBM
>>53
名前のない匿名な抽象型の例としてはC++かな
例えば以下のコードは構造的にobject.size()を使っていることで型付けされて
型パラメータTは構造的に無名な抽象型になる
template<class T> void print_size(T object) {
cout << "size: " << object.size() << endl;
}
その構造的に無名な抽象型を満たす任意の具象型で使うことができる
int main() {
std::string s = "abcde";
print_size(s); // size: 5
std::vector<int> v = {100, 200, 300};
print_size(v); // size: 3
}
もちろん名前がないために
多数の構造やその多段など複雑に込み入ってくると可読性が悪すぎたりコンパイルエラーがわかりにくい問題点も多いけどね
名前のない匿名な抽象型の例としてはC++かな
例えば以下のコードは構造的にobject.size()を使っていることで型付けされて
型パラメータTは構造的に無名な抽象型になる
template<class T> void print_size(T object) {
cout << "size: " << object.size() << endl;
}
その構造的に無名な抽象型を満たす任意の具象型で使うことができる
int main() {
std::string s = "abcde";
print_size(s); // size: 5
std::vector<int> v = {100, 200, 300};
print_size(v); // size: 3
}
もちろん名前がないために
多数の構造やその多段など複雑に込み入ってくると可読性が悪すぎたりコンパイルエラーがわかりにくい問題点も多いけどね
2026/09/26(土) 16:46:58.54ID:zBN8CwfD
>>53
「ダックタイピングはそういう判断自体をやっていない」と言えるかどうかは型付け・型検査の概念の広狭に依存する。
型付け・型検査の概念を狭く解釈すればそのようにいうことができるけど、一般に「ダックタイピングは構造的型付けの一種である」と言われるとき、ダックタイピングで想定された特定の属性をレシーバーのオブジェクトが持っているか否かは、型付け・型検査の一部として観念できる。
「ダックタイピングはそういう判断自体をやっていない」と言えるかどうかは型付け・型検査の概念の広狭に依存する。
型付け・型検査の概念を狭く解釈すればそのようにいうことができるけど、一般に「ダックタイピングは構造的型付けの一種である」と言われるとき、ダックタイピングで想定された特定の属性をレシーバーのオブジェクトが持っているか否かは、型付け・型検査の一部として観念できる。
2026/09/26(土) 22:22:51.92ID:n2TWK14F
>>55
それもダックタイピングだね
抽象型がプログラム上に型としては現れない
脳内にのみ存在するイマジナリー型なので匿名型とは違う
ちなみにそれをconceptで型制約する形にすれば
ダックタイピングじゃなく構造的型付けになる
それもダックタイピングだね
抽象型がプログラム上に型としては現れない
脳内にのみ存在するイマジナリー型なので匿名型とは違う
ちなみにそれをconceptで型制約する形にすれば
ダックタイピングじゃなく構造的型付けになる
2026/09/26(土) 22:32:39.52ID:n2TWK14F
>>56
Sequenceの必須メソッドは__len__と__getitem__なんだけど
`def foo(x: Sequence) -> Sequence`の中身が例えば`return [x[1], x[2]]`だったとしたら使われるのは__getitem__だけ
__getitem__呼び出し時にそのメソッドがあるかないかは判定はしてるがxの型がSequenceと互換性があるかどうかは判定していない
これがダックタイピング
Sequenceの必須メソッドは__len__と__getitem__なんだけど
`def foo(x: Sequence) -> Sequence`の中身が例えば`return [x[1], x[2]]`だったとしたら使われるのは__getitem__だけ
__getitem__呼び出し時にそのメソッドがあるかないかは判定はしてるがxの型がSequenceと互換性があるかどうかは判定していない
これがダックタイピング
2026/09/26(土) 23:01:58.09ID:BLRxOKC2
60デフォルトの名無しさん
2026/09/27(日) 08:39:38.65ID:WX540RHH 静的ダックタイピングと呼んだらええやん頭高市かよ
61デフォルトの名無しさん
2026/09/27(日) 08:42:16.05ID:kDXIIKaK2026/09/27(日) 09:38:40.25ID:kHe+LiQv
動的な構造的型付け=動的なダックタイピング
静的な構造的型付け=静的なダックタイピング
静的な構造的型付け=静的なダックタイピング
2026/09/27(日) 11:34:18.90ID:dEQoTM0i
>>58
言わんとするところは理解できるんだけど、プロトコルを基礎づける特殊メソッド全ての存在チェックがないから構造的型付けではないという理由で線を引くのであれば、
たとえば、そのコードでfooの中に__len__を参照するコードもあった場合とか、プロトコルを基礎づける特殊メソッドが単一の場合とかなら構造的型付けになるのかという話になる。
仮にそれらの場合もダックタイピングではあるが構造的型付けではないと整理するなら、それは結局、型付け・型検査がそのようにされるべきだという主張ということになる。
構造的な型の方の粒度をプロトコルより狭く設定する(たとえば、SupportsGetitemみたいな感じで)という構成も可能だろうし、あまり本質的な線引きにはなっていないように思うかな。
「動的型付けは型付けではない」という考え方自体は昔も今も非常に有力にあるし、結局、そういう言う考え方なんだろうなと思うけど。
言わんとするところは理解できるんだけど、プロトコルを基礎づける特殊メソッド全ての存在チェックがないから構造的型付けではないという理由で線を引くのであれば、
たとえば、そのコードでfooの中に__len__を参照するコードもあった場合とか、プロトコルを基礎づける特殊メソッドが単一の場合とかなら構造的型付けになるのかという話になる。
仮にそれらの場合もダックタイピングではあるが構造的型付けではないと整理するなら、それは結局、型付け・型検査がそのようにされるべきだという主張ということになる。
構造的な型の方の粒度をプロトコルより狭く設定する(たとえば、SupportsGetitemみたいな感じで)という構成も可能だろうし、あまり本質的な線引きにはなっていないように思うかな。
「動的型付けは型付けではない」という考え方自体は昔も今も非常に有力にあるし、結局、そういう言う考え方なんだろうなと思うけど。
2026/09/27(日) 12:37:50.98ID:QBKAmbSb
>>63
そういう線引きをしてるんじゃなくて型レベルのチェックはしてないよって話
線引きはシグニチャで要求される型と渡された値の型が互換性があるかどうかを型のレベルでチェックしてるかどうか
let x: Sequence = y; としたときにyの値の型がSequence型と互換性があるかどうかを型レベルでチェックしてるかどうか
そのチェックが構造的なら構造的型付けという線引き
そういう線引きをしてるんじゃなくて型レベルのチェックはしてないよって話
線引きはシグニチャで要求される型と渡された値の型が互換性があるかどうかを型のレベルでチェックしてるかどうか
let x: Sequence = y; としたときにyの値の型がSequence型と互換性があるかどうかを型レベルでチェックしてるかどうか
そのチェックが構造的なら構造的型付けという線引き
2026/09/27(日) 12:49:34.68ID:QBKAmbSb
匿名抽象型の話だけどOCamlはそれっぽい表現ができるみたいだね
let use_object
(x : < print : unit -> unit;
name : string;
reset : int -> unit >) =
print_endline x#name;
x#print ();
xは指定されたprint, name, resetメソッドを持つ必要がある
resetは実際使われてないが持ってないとコンパイルエラー
let use_object
(x : < print : unit -> unit;
name : string;
reset : int -> unit >) =
print_endline x#name;
x#print ();
xは指定されたprint, name, resetメソッドを持つ必要がある
resetは実際使われてないが持ってないとコンパイルエラー
2026/09/27(日) 13:23:57.86ID:dEQoTM0i
2026/09/27(日) 14:02:33.03ID:bt0wIF5T
オブジェクト指向って解析しずらいから嫌い。
2026/09/27(日) 14:57:38.19ID:+Ffvm/aN
2026/09/27(日) 17:56:09.43ID:sBAI0lnu
>>68
ダックタイピングと構造的型付けの境界だよね?
C++がコンパイル時に匿名抽象型的なものを内部的に作ってその型と渡された値の型の互換性をチェックしていたのならシグニチャには明記されないが構造的型付けと言うことはできたかもしれない
でも実際はそんなことはしてなくて渡された値の型でとりあえずテンプレートをインスタンス化してインスタンス化されたコードのコンパイルをしてみてメソッドが呼べなければエラーになるだけ
コンセプトを使えばインスタンス化される前に型レベルの互換性チェックが構造ベースで行われる
ダックタイピングと構造的型付けの境界だよね?
C++がコンパイル時に匿名抽象型的なものを内部的に作ってその型と渡された値の型の互換性をチェックしていたのならシグニチャには明記されないが構造的型付けと言うことはできたかもしれない
でも実際はそんなことはしてなくて渡された値の型でとりあえずテンプレートをインスタンス化してインスタンス化されたコードのコンパイルをしてみてメソッドが呼べなければエラーになるだけ
コンセプトを使えばインスタンス化される前に型レベルの互換性チェックが構造ベースで行われる
2026/09/27(日) 18:50:36.68ID:3YN1+PMa
71デフォルトの名無しさん
2026/09/27(日) 18:55:34.81ID:WX540RHH >>67
オブジェクト指向でリファクタしたらええやん
オブジェクト指向でリファクタしたらええやん
72デフォルトの名無しさん
2026/09/27(日) 18:58:06.60ID:WX540RHH Aの複雑さとBの複雑さを
同じ箇所にごちゃごちゃ書いたらわかりにくいだろ
オブジェクト指向ではAの複雑さをAの中に閉じ込める
Bの複雑さをBの中に閉じ込めるということをやって
複雑さをコントロールするんだよ
同じ箇所にごちゃごちゃ書いたらわかりにくいだろ
オブジェクト指向ではAの複雑さをAの中に閉じ込める
Bの複雑さをBの中に閉じ込めるということをやって
複雑さをコントロールするんだよ
73デフォルトの名無しさん
2026/09/27(日) 18:58:45.76ID:WX540RHH Aを修正したいときはAだけに集中してBは気にしなくて良いというのが理想
2026/09/27(日) 19:09:12.46ID:OVTBWj+n
>>69
構造的型付けを理解してなさすぎ
構造的とは実行コードだけ見て逆算で抽象型が決まるの
一方でそこで使われる役目のコンセプトはRustだとトレイトつまりJavaのインターフェースに近いポジション
コンセプトによる名前的型付けになる
これらは実行コードを見なくても先に抽象型が決まるの
構造的型付けを理解してなさすぎ
構造的とは実行コードだけ見て逆算で抽象型が決まるの
一方でそこで使われる役目のコンセプトはRustだとトレイトつまりJavaのインターフェースに近いポジション
コンセプトによる名前的型付けになる
これらは実行コードを見なくても先に抽象型が決まるの
2026/09/27(日) 22:15:08.26ID:XillenML
76デフォルトの名無しさん
2026/09/27(日) 22:25:00.19ID:6uVL41yj nominalは何らか型を制約する名称を用いて型付けされる。プログラムの構造が合致してなければコンパイルエラー。
structuralはプログラムの構造から型付けされる。名称はない。
structuralはプログラムの構造から型付けされる。名称はない。
2026/09/28(月) 00:25:48.20ID:Eld1IIYL
名前的型付けと構造的型付けの対比は静的型付けと動的型付けの対比とは独立した話だから、名前的型付けと構造的型付けの対比の文脈のはずなのにコンパイルとかコンパイラという言葉が出てきて、それで両者の違いを説明しようとするのは、それだけで一般的な説明としてはアウトだと思うわ。
2026/09/28(月) 01:38:54.80ID:bHv5uw6l
静的にエラーと言うべきだよな
79デフォルトの名無しさん
2026/09/28(月) 09:30:04.77ID:r6hSjsTa 細かい規約とかはどうでもいいが最低限変数、オブジェクトの型を用途別に区別が付くようにしろ。連想配列にしても使える候補を限定して定義し、コンパイル時にタイポチェックできるようにしろ。
何でもintかvoid*にしとけばOKだったCのオブジェクト指向とかは御免だ。
何でもintかvoid*にしとけばOKだったCのオブジェクト指向とかは御免だ。
2026/09/28(月) 09:56:16.04ID:HvQM2P3m
用途別というのをどれくらいの細かさのレベルで捉えるのか、ドメイン固有の仕様をできるだけ型システムに取り込んで型で表現できるようにするのを良しとするか、そうしないのかっていうのは結構考え方が分かれるところじゃない?
AdressとかPhoneNumberみたいな型をstringとは区別して定義して、型で仕様を表現するという考え方は本とかではしばしば見る。逆に関数型言語(の一部?)ではデータ型の種類は増やさず汎用的な関数でいろいろやるのが好まれるという主張も見る。どちらの方向性が良いのか、個人的な定見はないんだけど。
AdressとかPhoneNumberみたいな型をstringとは区別して定義して、型で仕様を表現するという考え方は本とかではしばしば見る。逆に関数型言語(の一部?)ではデータ型の種類は増やさず汎用的な関数でいろいろやるのが好まれるという主張も見る。どちらの方向性が良いのか、個人的な定見はないんだけど。
2026/09/28(月) 11:00:45.82ID:GprJgIHJ
関数の引数として受け取る場合
名前的型付け
・関数のシグネチャを見れば型がわかる/確定する
・関数内のコードを解読する必要がなく型がわかる/確定する
・そのため関数の開発者にも利用者にも理解がしやすい
・関数内のコードを解読して食い違いがあれば関数単体で実行前にエラーを出すことができる
・そのため開発時も保守更新時も効率がいい
機能的型付け
・関数のシグネチャで何も指定がない
・そのため関数の開発者はお手軽に使いやすい
・利用者にはわかりにくい
・関数内のコードを解読すれば型がわかる/確定する
・そのため関数を利用する側の各コードと突き合わせれば実行前にエラーを出せる可能性がある
・関数単体ではエラーは出ない
ここで「型がわかる/確定する」とは「具象型」または「特定の操作(群)が可能な抽象型」であることがわかる/確定するという意味である
名前的型付けの場合でもその抽象型に名前が付いているとは限らない
例えばインターフェースAとインターフェースBの両方を満たす抽象型はそれ自体の名前を持たないが抽象型としては確定する
名前的型付け
・関数のシグネチャを見れば型がわかる/確定する
・関数内のコードを解読する必要がなく型がわかる/確定する
・そのため関数の開発者にも利用者にも理解がしやすい
・関数内のコードを解読して食い違いがあれば関数単体で実行前にエラーを出すことができる
・そのため開発時も保守更新時も効率がいい
機能的型付け
・関数のシグネチャで何も指定がない
・そのため関数の開発者はお手軽に使いやすい
・利用者にはわかりにくい
・関数内のコードを解読すれば型がわかる/確定する
・そのため関数を利用する側の各コードと突き合わせれば実行前にエラーを出せる可能性がある
・関数単体ではエラーは出ない
ここで「型がわかる/確定する」とは「具象型」または「特定の操作(群)が可能な抽象型」であることがわかる/確定するという意味である
名前的型付けの場合でもその抽象型に名前が付いているとは限らない
例えばインターフェースAとインターフェースBの両方を満たす抽象型はそれ自体の名前を持たないが抽象型としては確定する
2026/09/28(月) 11:04:15.98ID:GprJgIHJ
2026/09/28(月) 12:18:20.77ID:4RLp7A79
型の識別をする際、名前的型付けは型の名前を基準とし、構造的片付けは型の構造を基準とする。部分型関係を定義するのに、名前的型付けは明示的な宣言(クラスやインターフェイスの継承など)を必要とするのに対し、構造的型付けは構造の包含関係等で判定できるので必ずしも明示的な宣言を必要としない……というのが基本的な違いだと思うけど。
構造的型付けだからといって型に名前を付けられないわけじゃないから、関数等の引数の型は普通に指定できるでしょ。自分はTypeScriptを書かないのでその型システムをきちんと知っているわけではないけれど、TypeScriptで関数の引数の型を指定できないなんて聞いたことがないし。
「実行前に〜」云々は静的型付けのことしか想定していないから、そもそも名前的型付けと構造的型付けの比較点として持ち出すのは的外れ。
構造的型付けだからといって型に名前を付けられないわけじゃないから、関数等の引数の型は普通に指定できるでしょ。自分はTypeScriptを書かないのでその型システムをきちんと知っているわけではないけれど、TypeScriptで関数の引数の型を指定できないなんて聞いたことがないし。
「実行前に〜」云々は静的型付けのことしか想定していないから、そもそも名前的型付けと構造的型付けの比較点として持ち出すのは的外れ。
2026/09/28(月) 12:27:18.60ID:oxabeVxG
2026/09/28(月) 12:35:41.34ID:4RLp7A79
何を言いたいのかよく分からないんだが、関数の引数の型付けという場面なら、構造的型付けの言語(たとえば、TypeScript)では引数の型の指定ができないという主張なの?
2026/09/28(月) 12:36:16.65ID:RUh9g+VI
Pythonでもあるまいし
2026/09/28(月) 12:38:06.03ID:zKqxj9Rf
>>85
型を明示的に指定したら名前的型付け
型を明示的に指定したら名前的型付け
2026/09/28(月) 12:41:30.14ID:Tw5Q7kzq
2026/09/28(月) 13:01:08.42ID:4RLp7A79
>>87
名前的型付けと構造的型付けという用語は、一般的には型の識別を型の名前によって行うか、型の構造によって行うかを指す用語として使われており、型に名前を付けているか否かを指す語ではないはずだけど。
というか、用語・概念の最初の定義の時点で一般的な理解から外れているのってどうなの……。
>>88
場面に応じて、名前的型付けと構造的型付けとが併用されることがあることは別に否定しないけれど、TypeScriptにおける関数等の引数の型は、基本的には構造的型付けで判定されるはずだよ(細かい仕様としてはいろいろあるみたいだけど)。少なくとも、関数等の引数の型を指定した場合に、そのことによって名前的型付けになるということはない。
名前的型付けと構造的型付けという用語は、一般的には型の識別を型の名前によって行うか、型の構造によって行うかを指す用語として使われており、型に名前を付けているか否かを指す語ではないはずだけど。
というか、用語・概念の最初の定義の時点で一般的な理解から外れているのってどうなの……。
>>88
場面に応じて、名前的型付けと構造的型付けとが併用されることがあることは別に否定しないけれど、TypeScriptにおける関数等の引数の型は、基本的には構造的型付けで判定されるはずだよ(細かい仕様としてはいろいろあるみたいだけど)。少なくとも、関数等の引数の型を指定した場合に、そのことによって名前的型付けになるということはない。
2026/09/28(月) 13:09:16.46ID:pNGkEIwI
>>55のC++の例は引数を束縛する名前がなく構造的型付けで静的ダックタイピングだけど
conceptを定義してその名前で束縛してやると名前的型付けになる
template <typename T>
concept HasSize = requires(T a) {
{ a.size() } -> std::convertible_to<std::size_t>;
};
void print_size(const HasSize auto& object) {
cout << "size: " << object.size() << endl;
}
conceptを定義してその名前で束縛してやると名前的型付けになる
template <typename T>
concept HasSize = requires(T a) {
{ a.size() } -> std::convertible_to<std::size_t>;
};
void print_size(const HasSize auto& object) {
cout << "size: " << object.size() << endl;
}
2026/09/28(月) 13:18:40.06ID:95RywFaz
2026/09/28(月) 13:20:19.76ID:RUh9g+VI
C++のテンプレートみたいなのはどうなん?
2026/09/28(月) 13:43:22.57ID:4RLp7A79
>>90
コンセプトはそもそも制約条件の記述であって、型じゃないでしょ。
>>91
オレオレ定義で押し通そうとするのは何なん。検索するなり、AIに聞くなりして「名前的型付け」「構造的型付け」の意味を確認するところから始めた方が良いと思うが。
たとえば、関数の引数がインターフェイスA型のオブジェクトを受け取るシグネチャになっているとき、名前的型付けであれば、Aと同じ構造を持つが名前が異なるインターフェイスB型のオブジェクトは引数として渡せないことになるが、TypeScriptはそういう仕様になっている? それともオレオレ定義の名前的型付けでは、そういう名前の異なる型同士の間でも同一性・互換性を認めるってするの?
コンセプトはそもそも制約条件の記述であって、型じゃないでしょ。
>>91
オレオレ定義で押し通そうとするのは何なん。検索するなり、AIに聞くなりして「名前的型付け」「構造的型付け」の意味を確認するところから始めた方が良いと思うが。
たとえば、関数の引数がインターフェイスA型のオブジェクトを受け取るシグネチャになっているとき、名前的型付けであれば、Aと同じ構造を持つが名前が異なるインターフェイスB型のオブジェクトは引数として渡せないことになるが、TypeScriptはそういう仕様になっている? それともオレオレ定義の名前的型付けでは、そういう名前の異なる型同士の間でも同一性・互換性を認めるってするの?
2026/09/28(月) 13:44:16.08ID:ryNukvdc
似てるようで別なこと
型推論
不明な型の変数がその後の使われ方で逆伝播して具象型が定まること
構造的型付け
不明な型の変数がその後の使われ方の構造によって制限されて抽象型が定まること
構造的マッチング
既に型が定まってる変数に対してその型と同じ構造のデータがマッチングないし代入されること
型推論
不明な型の変数がその後の使われ方で逆伝播して具象型が定まること
構造的型付け
不明な型の変数がその後の使われ方の構造によって制限されて抽象型が定まること
構造的マッチング
既に型が定まってる変数に対してその型と同じ構造のデータがマッチングないし代入されること
95デフォルトの名無しさん
2026/09/28(月) 14:22:27.24ID:l/ctBmDQ 構造的型付けとダックタイピングはWikipediaの型システムの解説が良く整理されていると思うけど、これをベースに考えればいいんじゃない?
https://ja.wikipedia.org/wiki/%E5%9E%8B%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0
オレオレ定義を使うなら、Wikipediaとの差分と、Wikipediaと違う定義にする理由くらいは明示してほしいところ。
https://ja.wikipedia.org/wiki/%E5%9E%8B%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0
オレオレ定義を使うなら、Wikipediaとの差分と、Wikipediaと違う定義にする理由くらいは明示してほしいところ。
2026/09/28(月) 14:40:40.53ID:n9ZOKaKy
2026/09/28(月) 15:00:09.45ID:Rqiydlvp
>>90
print_sizeの引数として渡されたobjectの型が明示的にHasSizeを実装してると宣言してある場合だけ互換性がある型として扱われるのならnominal typing
実際はobjectの型が構造的にHasSizeを満たしていれば互換性がある型として扱われるのでそれはstructural typing
print_sizeの引数として渡されたobjectの型が明示的にHasSizeを実装してると宣言してある場合だけ互換性がある型として扱われるのならnominal typing
実際はobjectの型が構造的にHasSizeを満たしていれば互換性がある型として扱われるのでそれはstructural typing
2026/09/28(月) 15:06:02.29ID:v+4ryWt8
2026/09/28(月) 15:48:54.81ID:4RLp7A79
C++のテンプレートは構造的型付けであると断言するものより、構造的型付け「に近い」とか構造的型付け「的」とか、ちょっと留保の余地を残した書き振りの説明の方が多くない?
名前的型付けと構造的型付けの対比は主にサブタイピング多相の文脈でクローズアップされるのに対し、テンプレートはパラメトリック多相の系譜だからちょっと区別されているのかなという印象だけど。
stringとvectorは同じ型とされているわけじゃないけど、sizeを持つという点で同じ構造を持っており、それによりprint_sizeとの関係では互換的に使うことが認められる。その意味で構造的型付け「的」ではあるけれども部分型関係があるわけじゃないから、名前的型付けと構造的型付けの対比として典型的に持ち出される場面とはちょっと違う……ということだと思うけど。
名前的型付けと構造的型付けの対比は主にサブタイピング多相の文脈でクローズアップされるのに対し、テンプレートはパラメトリック多相の系譜だからちょっと区別されているのかなという印象だけど。
stringとvectorは同じ型とされているわけじゃないけど、sizeを持つという点で同じ構造を持っており、それによりprint_sizeとの関係では互換的に使うことが認められる。その意味で構造的型付け「的」ではあるけれども部分型関係があるわけじゃないから、名前的型付けと構造的型付けの対比として典型的に持ち出される場面とはちょっと違う……ということだと思うけど。
100デフォルトの名無しさん
2026/09/28(月) 15:56:55.52ID:0CghAh2a >>54
クラスとインターフェースはツリーと言っても向きが真逆だよ
ツリーと言うからには多重継承を許す極一部の言語を除く場合だろうけどその時
クラス継承のツリーは下方向に多数になり得る
一方でクラスから見てインターフェースは上で上方向が多数になり得る
クラスとインターフェースはツリーと言っても向きが真逆だよ
ツリーと言うからには多重継承を許す極一部の言語を除く場合だろうけどその時
クラス継承のツリーは下方向に多数になり得る
一方でクラスから見てインターフェースは上で上方向が多数になり得る
101デフォルトの名無しさん
2026/09/28(月) 16:37:41.18ID:1uMJeQMq いうほど真逆か?
102デフォルトの名無しさん
2026/09/28(月) 16:48:24.28ID:BGoMxURs >>100
構造的型付けを勘違いしていたことを自覚したので他の話題に切り替えたい模様
構造的型付けを勘違いしていたことを自覚したので他の話題に切り替えたい模様
103デフォルトの名無しさん
2026/09/28(月) 16:48:50.32ID:Q3Hh51qJ 継承の向きを揃えると逆だね
多対1 多数のインターフェイス→自分
1対多 自分→多数のサブクラス
多対1 多数のインターフェイス→自分
1対多 自分→多数のサブクラス
104デフォルトの名無しさん
2026/09/28(月) 16:52:08.39ID:YePwWPQV >>99は反省してるようだからイジメてやるなよ
105デフォルトの名無しさん
2026/09/28(月) 18:58:55.92ID:SXsOChla106デフォルトの名無しさん
2026/09/28(月) 19:15:58.44ID:4RLp7A79107デフォルトの名無しさん
2026/09/28(月) 19:20:18.74ID:6QPWoNxk >>106
実行前に分かるか分からないかで2つに分かれてるなら致命的な違いに見える
実行前に分かるか分からないかで2つに分かれてるなら致命的な違いに見える
108デフォルトの名無しさん
2026/09/28(月) 20:35:55.08ID:4RLp7A79 「分かれてるなら〜」じゃなくて自分で調べたら?
名前的型付けと構造的型付けの対比は、静的型付けと動的型付けの対比とは独立している。したがって、名前的型付け・構造的型付けのいずれであるにせよ、静的型付けと動的型付けのいずれとも結び付き得る。
たとえばPythonは、(プロトコルなどはあるものの)名前的型付けが基本の動的型付け言語、TypeScriptは構造的型付けが基本の静的型付け言語。>>81がどれだけナンセンスなことを書いているのか、いい加減に理解してよ。
名前的型付けと構造的型付けの対比は、静的型付けと動的型付けの対比とは独立している。したがって、名前的型付け・構造的型付けのいずれであるにせよ、静的型付けと動的型付けのいずれとも結び付き得る。
たとえばPythonは、(プロトコルなどはあるものの)名前的型付けが基本の動的型付け言語、TypeScriptは構造的型付けが基本の静的型付け言語。>>81がどれだけナンセンスなことを書いているのか、いい加減に理解してよ。
109デフォルトの名無しさん
2026/09/28(月) 20:59:40.77ID:uWV6IayP >>107
さっき上げたwikipediaにまとまってるけど、
「名前的型付けとは、システムが保持しているプログラム要素の参照情報上の型の名前を見て、データ値の型を識別するスタイルである。
構造的型付けとは、参照情報上の型の名前を見ないで、データ値本体の分析でデータ値の型を識別するスタイルである。」
型の互換性判定で名前を見るか型の構造を見るかの違いだよ。
その結果、名前的型付けは名前同士の関係を実際に使用する前に明示する必要があって、型同士の依存関係をコーティング早期に強くする必要がある。
構造的型付けと名前的型付けの違いが効いてくるのは設計の話で、実行前か実行時かはあんまり効いてこないかと。
さっき上げたwikipediaにまとまってるけど、
「名前的型付けとは、システムが保持しているプログラム要素の参照情報上の型の名前を見て、データ値の型を識別するスタイルである。
構造的型付けとは、参照情報上の型の名前を見ないで、データ値本体の分析でデータ値の型を識別するスタイルである。」
型の互換性判定で名前を見るか型の構造を見るかの違いだよ。
その結果、名前的型付けは名前同士の関係を実際に使用する前に明示する必要があって、型同士の依存関係をコーティング早期に強くする必要がある。
構造的型付けと名前的型付けの違いが効いてくるのは設計の話で、実行前か実行時かはあんまり効いてこないかと。
110デフォルトの名無しさん
2026/09/28(月) 21:04:39.99ID:fhlg/LcG >>108
Pythonはダックタイピングだから構造的型付け
Pythonはダックタイピングだから構造的型付け
111デフォルトの名無しさん
2026/09/28(月) 21:13:27.25ID:jGOybPCK >>83
TypeScriptは構造的部分型だよ
TypeScriptは構造的部分型だよ
112デフォルトの名無しさん
2026/09/28(月) 22:16:11.65ID:PhpUVe3q113デフォルトの名無しさん
2026/09/28(月) 22:39:32.71ID:4RLp7A79114デフォルトの名無しさん
2026/09/28(月) 22:42:45.58ID:HLDe4fz7 構造的型付けは欠陥だらけなので採用しているプログラミング言語は片手で数えられる
ほとんどの言語は欠陥だらけの構造的型付けを採用しなかった
ほとんどの言語は欠陥だらけの構造的型付けを採用しなかった
115デフォルトの名無しさん
2026/09/28(月) 23:17:01.30ID:1uMJeQMq ハルシネーション治せる?
116デフォルトの名無しさん
2026/09/29(火) 01:40:51.63ID:/y8pr6yq 構造的型付け言語でまともな開発するわけではないから特に問題はない
スクリプトとして使う分には合ってる
スクリプトとして使う分には合ってる
117デフォルトの名無しさん
2026/09/29(火) 07:49:54.00ID:rpd4Agfm まともな言語なら構造的型付けと名前的型付けを併用できるだろ。
OCamlみたいに構造的部分型などを活用して設計を後回しにできるメリットは大きい。
OCamlみたいに構造的部分型などを活用して設計を後回しにできるメリットは大きい。
118デフォルトの名無しさん
2026/09/29(火) 09:05:53.80ID:ILQcCoh0 構造的型付けを採用しているのはTypeScriptとかGoといった比較的新しい言語だし、名前的型付けの言語でも構造的型付けの要素を追加する動きは少なくない。たとえばPythonは3.8でtyping.Protocolを追加している。
構造的型付けにはしばしば指摘されている欠点があるのでそれに対応する必要はあるものの、クラスやインターフェイスの継承といった明示的な宣言をしなくても部分型関係を作れるというのは非常に大きなメリットだと思うよ。既存の継承ツリーに手を加えられるとは限らない(仮に手を加えられたとしてもその分ツリーは大きく複雑になる)からね。個人的には『ロバストPython』に出ていた飲食店のメニューを表す継承ツリーにSplittableという要素を追加するという例が面白かった。
構造的型付けにはしばしば指摘されている欠点があるのでそれに対応する必要はあるものの、クラスやインターフェイスの継承といった明示的な宣言をしなくても部分型関係を作れるというのは非常に大きなメリットだと思うよ。既存の継承ツリーに手を加えられるとは限らない(仮に手を加えられたとしてもその分ツリーは大きく複雑になる)からね。個人的には『ロバストPython』に出ていた飲食店のメニューを表す継承ツリーにSplittableという要素を追加するという例が面白かった。
119デフォルトの名無しさん
2026/09/29(火) 10:00:30.01ID:cCKQULA1120デフォルトの名無しさん
2026/09/29(火) 10:12:07.14ID:Vfkc83jJ クラス継承のツリーが癌
健全なオブジェクト指向には不要だった部分
健全なオブジェクト指向には不要だった部分
121デフォルトの名無しさん
2026/09/29(火) 10:41:44.88ID:BHNGK2GU 間違ったオブジェクト指向を教えられアンチオブジェクト指向になった人と
構造的型付けとは静的なダックタイピングだという間違った知識いまだに信じてる人と
構造的型付けと名前的片付けの区別がつかない人が
きれいに重なってるのが面白い
原因はやっぱり20年以上前から知識をアップデートできてないからだろうな
構造的型付けとは静的なダックタイピングだという間違った知識いまだに信じてる人と
構造的型付けと名前的片付けの区別がつかない人が
きれいに重なってるのが面白い
原因はやっぱり20年以上前から知識をアップデートできてないからだろうな
122デフォルトの名無しさん
2026/09/29(火) 10:48:33.13ID:UKR2p5le 構造的型付けは型システムの安全性を失くす危険因子
安全性を重視するなら絶対に導入してはいけない
安全性を重視するなら絶対に導入してはいけない
123デフォルトの名無しさん
2026/09/29(火) 11:01:53.27ID:NSQyi4O1 構造的型付けを導入してしまったTypeScriptは苦しんでるよな
構造が同じなら同じ型になるのは型安全性を乱す致命的な間違いだった
そこでTypeScriptは型を区別するために隠しフィールドを増やすという本末転倒な方法を編み出した
構造が同じなら同じ型になるのは型安全性を乱す致命的な間違いだった
そこでTypeScriptは型を区別するために隠しフィールドを増やすという本末転倒な方法を編み出した
124デフォルトの名無しさん
2026/09/29(火) 12:08:51.86ID:ZiRQx0wb 構造的型付けを安全にするのは簡単だよ
①構造に名前を付ける
②同じ構造でも名前が異なるなら区別する
③各型やクラスはどの構造を持っているのか名前で宣言する
これで安全になるよ
①②③は必須だよ
①構造に名前を付ける
②同じ構造でも名前が異なるなら区別する
③各型やクラスはどの構造を持っているのか名前で宣言する
これで安全になるよ
①②③は必須だよ
125デフォルトの名無しさん
2026/09/29(火) 12:11:29.61ID:vzAaEt5X 構造体もそれぞれ目的が違うんだから同じ内容に見えても別名にするだろうし、名前だって目的に沿った名前にするから当然違う名前になる
126デフォルトの名無しさん
2026/09/29(火) 12:27:42.44ID:YWwtg6nn127デフォルトの名無しさん
2026/09/29(火) 12:29:26.17ID:vzAaEt5X >>126
それは最悪だな、機能追加や変更がやりづらいw
それは最悪だな、機能追加や変更がやりづらいw
128デフォルトの名無しさん
2026/09/29(火) 12:35:20.45ID:CNghhHUF 構造的型付けでもその構造型に名前をつけることはよくあるけれども、型の区別を名前で行うならばそれはもはや構造的型付けではないでしょ。
構造的型付けのメリットを活かしつつ、欠点をどうフォローするかは構造的型付けを取り入れた各言語で模索中ってところじゃないの。Pythonみたいな言語で部分的に構造的型付けを取り入れているだけの分にはほぼメリットしか感じないけど、TypeScriptみたいな純粋な構造的型付け言語でどうなのかというのは、自分はTypeScript を知らないので分からないな。結構苦労するのか、それともそれなりに対処法が確立されているので実際的にはさほど問題にならないのか。
構造的型付けのメリットを活かしつつ、欠点をどうフォローするかは構造的型付けを取り入れた各言語で模索中ってところじゃないの。Pythonみたいな言語で部分的に構造的型付けを取り入れているだけの分にはほぼメリットしか感じないけど、TypeScriptみたいな純粋な構造的型付け言語でどうなのかというのは、自分はTypeScript を知らないので分からないな。結構苦労するのか、それともそれなりに対処法が確立されているので実際的にはさほど問題にならないのか。
129デフォルトの名無しさん
2026/09/29(火) 12:40:43.77ID:tY+uLrS/130デフォルトの名無しさん
2026/09/29(火) 12:43:03.74ID:vzAaEt5X プリミティブなレベルでの構造的型付けならいいが
そんなものは言語ライブラリレベルでしか成立しなくて
アプリ階層の構造なんてそれこそ流動的で開発終了した後でさえ変更が入るってのにw
そんなものは言語ライブラリレベルでしか成立しなくて
アプリ階層の構造なんてそれこそ流動的で開発終了した後でさえ変更が入るってのにw
131デフォルトの名無しさん
2026/09/29(火) 12:48:16.40ID:qMOOoGYG >>128
TypeScriptでは構造的型付けの問題点を解決するために安全なプログラムでは名前で区別するようになったよ
ブランディングと呼ばれる手法が用いられていて構造に名前を入れることを必須にしてその名前によって構造を区別してるよ
interface UserId {
__brand: "UserId";
id: number;
}
interface ProductId {
__brand: "ProductId";
id: number;
}
TypeScriptでは構造的型付けの問題点を解決するために安全なプログラムでは名前で区別するようになったよ
ブランディングと呼ばれる手法が用いられていて構造に名前を入れることを必須にしてその名前によって構造を区別してるよ
interface UserId {
__brand: "UserId";
id: number;
}
interface ProductId {
__brand: "ProductId";
id: number;
}
132デフォルトの名無しさん
2026/09/29(火) 12:59:09.82ID:ykmES0Hv 構造的型付けは欠陥品であることが明白になった
133デフォルトの名無しさん
2026/09/29(火) 13:02:40.21ID:CNghhHUF 同じ構造でも名前が違うなら区別する(②)というときの「名前」が型の名前ならそれは構造的型付けではないし、型安全性みたいな用語をふわっと使うのもどうかと思うけど……。
>>131
型の識別のためだけのダミーな属性を入れるということなので、構造的型付けの理念からは一歩後退ということになるんだろうけど、少なくとも構造的型付けオンリーでやるのはちょっと厳しいというのは共通認識になっているということなんだろうね。
>>131
型の識別のためだけのダミーな属性を入れるということなので、構造的型付けの理念からは一歩後退ということになるんだろうけど、少なくとも構造的型付けオンリーでやるのはちょっと厳しいというのは共通認識になっているということなんだろうね。
134デフォルトの名無しさん
2026/09/29(火) 13:05:35.23ID:hV2YmEQE バカの論理やめえやw
それはうなぎの血をがぶ飲みしたら体を壊すからうなぎは体に悪いと言ってるようなものだろうがバカがw
それはうなぎの血をがぶ飲みしたら体を壊すからうなぎは体に悪いと言ってるようなものだろうがバカがw
135デフォルトの名無しさん
2026/09/29(火) 13:06:04.65ID:vzAaEt5X 例えが意味不明
136デフォルトの名無しさん
2026/09/29(火) 13:14:44.89ID:hV2YmEQE 意味不明という言葉を使うやつ例外なくバカです、うなぎでバカが釣れました、リリースします
137デフォルトの名無しさん
2026/09/29(火) 13:23:04.24ID:XIbqHuSI >>131
それが①②③を満たしているか確認してみると
>>124
>①構造に名前を付ける
interface UserId と
__brand: "UserId"; で二つも名前がついてるから合格
しかし二重に名前を付けざるを得ない点は辛いところだね
>②同じ構造でも名前が異なるなら区別する
構造の中に __brand: "UserId"; という名前を持ったことで区別できるようになったので合格
>③各型やクラスはどの構造を持っているのか名前で宣言する
これは各型やクラスに __brand: "UserId"; を持つことになるのだろうから合格
①②③を満たしているね
interfaceで名前を二重に持たざるを得ない欠点があるから100点はあげられないけれど
それが①②③を満たしているか確認してみると
>>124
>①構造に名前を付ける
interface UserId と
__brand: "UserId"; で二つも名前がついてるから合格
しかし二重に名前を付けざるを得ない点は辛いところだね
>②同じ構造でも名前が異なるなら区別する
構造の中に __brand: "UserId"; という名前を持ったことで区別できるようになったので合格
>③各型やクラスはどの構造を持っているのか名前で宣言する
これは各型やクラスに __brand: "UserId"; を持つことになるのだろうから合格
①②③を満たしているね
interfaceで名前を二重に持たざるを得ない欠点があるから100点はあげられないけれど
138デフォルトの名無しさん
2026/09/29(火) 14:08:29.60ID:ZkEmXw6z 構造的型付けの欠陥を対処したら名前的型付けになりました草
139デフォルトの名無しさん
2026/09/29(火) 14:47:56.91ID:hV2YmEQE 柔軟性が失われてて大爆笑
レスを投稿する
ニュース
- 【日中】中国の王毅外相が関係正常化の「条件」を提示 岩屋前外相との会談で ★3 [煮卵★]
- 【バレーボール】男子・日本代表 髙橋藍の兄、高橋塁…同性愛者であると公表「初めて自分自身を認めることができました」 ★2 [阿弥陀ヶ峰★]
- 物価高に7割超”年収追い付かず” 必要な年収増加額は平均約38万円 住友生命 [首都圏の虎★]
- 「何をもって『オール沖縄の終焉』というのか」 沖縄・玉城デニー知事が退任会見で疑問視 [少考さん★]
- 日本の総人口、1億2297万人 (−2.5%) [少考さん★]
- 【🇯🇵】日の丸を傷つけたら処罰「国旗損壊罪」に日弁連が即時廃止求める「表現の自由そのものが失われかねない」 ★3 [少考さん★]
- 【悲報】安倍晋三への侮辱、厳罰化へ [412290841]
- 【訃報】株はもう上がらない、日経平均7万はもう戻らない、助からない、一生マイナス [943688309]
- 【悲報】亜月ねね 先生の弁護士を名乗るIPアドレスと810chで荒らし認定されて晒されたIPアドレスが完全に同一であることが確認された [841411289]
- 【実況】博衣こよりのえちえちホロドリ水着ガチャ🧪★5
- 高市政府「ヤバ…ネットの中傷、賠償額低すぎ」超絶高額化へ [245325974]
- 【高市悲報】AIマンガの作り方の本、作例のクオリティが高すぎると話題 もうこれ漫画家廃業だろ [158478931]