過去スレ
オブジェクト指向はオワコン (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:R0E4hCxI159デフォルトの名無しさん
2026/09/29(火) 18:21:33.82ID:hV2YmEQE >>158
で、型安全性とは何かね? おーん?w
で、型安全性とは何かね? おーん?w
160デフォルトの名無しさん
2026/09/29(火) 18:46:03.92ID:HUZmERan TypeScriptにおけるオブジェクトの型ってのはobject shapeのこと
typeやinterfaceはobject shapeのaliasでしかない
名前的型付け脳はまずここでつまづく
typeやinterfaceはobject shapeのaliasでしかない
名前的型付け脳はまずここでつまづく
161デフォルトの名無しさん
2026/09/29(火) 19:10:28.30ID:Dbg3h22T 「型安全性」とやらに着目してはいけない
少し引いてみるといつも同じ構造になってる
いつもいつも同じ構造になってる
〇〇凄い→〇〇を備えてる言語凄い→Rust凄い→Rust応援隊の俺も凄い
これやりたいだけだからその子は
みんなも薄々見抜いてて遊んでんだろこれ
少し引いてみるといつも同じ構造になってる
いつもいつも同じ構造になってる
〇〇凄い→〇〇を備えてる言語凄い→Rust凄い→Rust応援隊の俺も凄い
これやりたいだけだからその子は
みんなも薄々見抜いてて遊んでんだろこれ
162デフォルトの名無しさん
2026/09/29(火) 19:39:51.45ID:ILQcCoh0 Rust凄いがやりたいなら、構造的型付けは型安全性を欠くみたいな意味不明な戯言ではなく、Rustのトレイトのような機能がある言語では、構造的型付けの強みは相対的に価値が低くなるとか、そういった方向性の立論にするのがふつうじゃない?
163デフォルトの名無しさん
2026/09/29(火) 20:13:03.38ID:70bcaihA >>160
というよりも他の言語と違ってJavaScriptのオブジェクトは形は違えど1種類の型しかないことが敗因だよな
TypeScriptでもそれぞれの型注釈をそのまま直接書くかinterfaceやtypeで名前付けするくらいしかできないことが本質だよな
というよりも他の言語と違ってJavaScriptのオブジェクトは形は違えど1種類の型しかないことが敗因だよな
TypeScriptでもそれぞれの型注釈をそのまま直接書くかinterfaceやtypeで名前付けするくらいしかできないことが本質だよな
164デフォルトの名無しさん
2026/09/29(火) 20:18:06.79ID:1bOZFsrl PythonだとJS/TSのプリミティブ相当まで全てがオブジェクト
しかしオブジェクトにきちんと型があって分かれているからJS/TSのような酷い状況になってない
しかしオブジェクトにきちんと型があって分かれているからJS/TSのような酷い状況になってない
165デフォルトの名無しさん
2026/09/29(火) 20:29:39.91ID:4VX1dv24 オブジェクトに型の名前を付けて区別する機能が元々のJavaScriptにないんだよ
唯一できる区別が構造による区別だね
TypeScriptは構造的型付けが優れているから選んだのではなく仕方なくそうせざるを得なったに過ぎないんだよ
唯一できる区別が構造による区別だね
TypeScriptは構造的型付けが優れているから選んだのではなく仕方なくそうせざるを得なったに過ぎないんだよ
166デフォルトの名無しさん
2026/09/29(火) 21:47:36.93ID:moHWHs+C >>162
Pythonがiteratorを導入する時に後からiterator用の新たなABCを適用できないため
構造的に__next__と__iter__を持つオブジェクトをiteratorにした話も該当することに気付いた
Rustのトレイトはインタフェースや抽象クラスと違って後から新たなトレイトを適用できる柔軟性があるから
そのケースも構造的型付けにしなくて済むね
Pythonがiteratorを導入する時に後からiterator用の新たなABCを適用できないため
構造的に__next__と__iter__を持つオブジェクトをiteratorにした話も該当することに気付いた
Rustのトレイトはインタフェースや抽象クラスと違って後から新たなトレイトを適用できる柔軟性があるから
そのケースも構造的型付けにしなくて済むね
167デフォルトの名無しさん
2026/09/29(火) 22:07:19.83ID:ShrXkvl+ >>163
誰がどう見ても複おじのオツムが最大の敗因
誰がどう見ても複おじのオツムが最大の敗因
168デフォルトの名無しさん
2026/09/29(火) 23:45:30.70ID:Dbg3h22T あたまの悪さなのか
こころの病気なのか
いずれにせよ
気の毒なもんですよ
こころの病気なのか
いずれにせよ
気の毒なもんですよ
169デフォルトの名無しさん
2026/09/30(水) 00:06:09.07ID:g8JP9qrN170デフォルトの名無しさん
2026/09/30(水) 00:15:15.02ID:HyImc2s0 オブジェクト指向プログラミングに不要なクラスの継承を付けてしまったことはJavaの生みの親も後悔してた
171デフォルトの名無しさん
2026/09/30(水) 07:59:03.52ID:XxnCMSRV 名前的型付けで(型にしろインターフェイスにしろ)継承以外で互換性を指示する方法はないんじゃないんかな。
構造的型付けをサポートすれば解決するけど。
構造的型付けをサポートすれば解決するけど。
172デフォルトの名無しさん
2026/09/30(水) 08:27:25.74ID:TLEZAlhX >>170
お前はそれを知ってどう思った?
お前はそれを知ってどう思った?
173デフォルトの名無しさん
2026/09/30(水) 08:31:57.90ID:TLEZAlhX 昔は
・Interfaceを作る
・Interfaceを実装するAbstract Classを作る
・Abstract Classを継承してClassを作る
というのが一連の流れじゃったなあ
Abstract Classを挟むのはInterfaceのメソッドをClassごとに実装するのが大変だったから
いまは簡単になったんかいの?
・Interfaceを作る
・Interfaceを実装するAbstract Classを作る
・Abstract Classを継承してClassを作る
というのが一連の流れじゃったなあ
Abstract Classを挟むのはInterfaceのメソッドをClassごとに実装するのが大変だったから
いまは簡単になったんかいの?
174デフォルトの名無しさん
2026/09/30(水) 09:08:28.09ID:5R37cYoe 現代のオブジェクト指向プログラミング
・クラス継承は使わない
・共通の変数(群)がある時はそれを独立させて合成して委譲する
・他に共通のメソッドがある時は共通インタフェースを作ってそれを実装する
・クラス継承は使わない
・共通の変数(群)がある時はそれを独立させて合成して委譲する
・他に共通のメソッドがある時は共通インタフェースを作ってそれを実装する
175デフォルトの名無しさん
2026/09/30(水) 09:24:54.34ID:TLEZAlhX …簡単に…なったの…?
176デフォルトの名無しさん
2026/09/30(水) 09:32:57.89ID:BI+U5C/y >>175
逆
逆
177デフォルトの名無しさん
2026/09/30(水) 09:46:49.16ID:mDcPE0qK 何を簡単と呼ぶかの差かな~
クラス継承をしていくと密結合にデブって複雑なモノリシックになるから
最近は簡単に分けてクラス継承を使わずに合成しましょうって感じ
クラス継承をしていくと密結合にデブって複雑なモノリシックになるから
最近は簡単に分けてクラス継承を使わずに合成しましょうって感じ
178デフォルトの名無しさん
2026/09/30(水) 10:01:01.98ID:YF5B3cUi >>171
名前的型付けと構造的型付けで違いが出るのはサブタイピング多相の文脈だけじゃない? テンプレートなどのパラメトリック多相とか、Rustのトレイト(アドホック多相の一種?)とかは、特に両者の対比とは関係ないと思う。
名前的型付けと構造的型付けで違いが出るのはサブタイピング多相の文脈だけじゃない? テンプレートなどのパラメトリック多相とか、Rustのトレイト(アドホック多相の一種?)とかは、特に両者の対比とは関係ないと思う。
179デフォルトの名無しさん
2026/09/30(水) 10:05:25.31ID:ZUa3ugSV クラス継承はほんと害悪だが
人にもコンピュータにも
人にもコンピュータにも
180デフォルトの名無しさん
2026/09/30(水) 10:09:40.97ID:ZUa3ugSV 分散パイプラインという現実の工場と同じ流れになった
それ以外は些末
ベルトコンベアを詰まらせないことが至上命題
それ以外は些末
ベルトコンベアを詰まらせないことが至上命題
181デフォルトの名無しさん
2026/09/30(水) 11:31:06.45ID:l3EYRoUC >>173
Beansっていつから言われなくなったのか
Beansっていつから言われなくなったのか
182デフォルトの名無しさん
2026/09/30(水) 11:38:31.94ID:QF/NFjiQ >>178
もちろんそんなことはない
もちろんそんなことはない
183デフォルトの名無しさん
2026/09/30(水) 12:04:03.36ID:XxnCMSRV184デフォルトの名無しさん
2026/09/30(水) 12:21:59.10ID:BI+U5C/y WindowsのGUIパーツが継承だらけなんだが
185デフォルトの名無しさん
2026/09/30(水) 12:23:50.66ID:Ctyzurfk 隠し名前フィールドまで設けて構造的型付けを使う必要性がないもんな
メリットなし
メリットなし
186デフォルトの名無しさん
2026/09/30(水) 12:27:16.98ID:TLEZAlhX >>181
Java BeansはGUIアプリの技術だからな
GUIアプリがWebアプリで代替されるようになって
GUIコンポネント自体が廃れたのよね
Java Beansは20年前に死にました
Windowsを作ってるMicrosoftでさえ
WindowsのGUIよりもWebアプリを選んで
VSCode作ってるくらいだからな
ちなみにVSCode作ったのはオブジェクト指向のデザインパターンを考えた
GoFの一人エリック・ガンマ
Java BeansはGUIアプリの技術だからな
GUIアプリがWebアプリで代替されるようになって
GUIコンポネント自体が廃れたのよね
Java Beansは20年前に死にました
Windowsを作ってるMicrosoftでさえ
WindowsのGUIよりもWebアプリを選んで
VSCode作ってるくらいだからな
ちなみにVSCode作ったのはオブジェクト指向のデザインパターンを考えた
GoFの一人エリック・ガンマ
187デフォルトの名無しさん
2026/09/30(水) 12:53:30.16ID:o884dnKq もう自分じゃ書かないからどんなに記述がめんどくても実行パフォーマンスで最適なら構わん
AIにとって管理しやすいわけわからん言語になるんだろうなあ
AIにとって管理しやすいわけわからん言語になるんだろうなあ
188デフォルトの名無しさん
2026/09/30(水) 12:56:15.55ID:zv7jPpbX 道具にはそれぞれに適した用途と使い方があるにも関わらず
不適切な用途に使ったり不適切な使い方をしたりして
不都合な結果が出るとこの道具は使えないなどという結論を出す
もちろん本当に使えないのは道具ではなくて複おじのオツムです
不適切な用途に使ったり不適切な使い方をしたりして
不都合な結果が出るとこの道具は使えないなどという結論を出す
もちろん本当に使えないのは道具ではなくて複おじのオツムです
189デフォルトの名無しさん
2026/09/30(水) 12:57:53.49ID:jXloo4hX AIにRustで書かせる例がどんどん増えてるね
メモリ消費が少なく速くて安全な言語が一番いいみたい
メモリ消費が少なく速くて安全な言語が一番いいみたい
190デフォルトの名無しさん
2026/09/30(水) 12:59:21.73ID:o884dnKq 俺もRUSTにしてる、自分で見たくならないから
191デフォルトの名無しさん
2026/09/30(水) 14:17:14.80ID:nOWz/ZAL >>183
同一性の判断基準が異なるというのはもちろんだけど、>>171で話題にされているのが型の互換性だったからね。
型の別名というのが型エイリアス(処理系によって同視される型)のことなら名前的型付けと構造的型付けとで違いはないでしょう。ニュータイプ型の別名ならたしかに違いが出てくるけど、それは構造的型付けの方は余計に一手間掛かるという方向の違いだよね。
いずれにせよ名前的型付けにおいて、型の互換性を指示する方法として継承以外のものがあるという点は変わらないと思うけど。
個人的には名前的型付けの型システムに構造的型付けの機能を追加することについては、比較的好意的に捉えているけどね。Rustみたいな言語だとあまり必要性はないのかもしれないけれど、Pythonとかではかなりありがたい。
同一性の判断基準が異なるというのはもちろんだけど、>>171で話題にされているのが型の互換性だったからね。
型の別名というのが型エイリアス(処理系によって同視される型)のことなら名前的型付けと構造的型付けとで違いはないでしょう。ニュータイプ型の別名ならたしかに違いが出てくるけど、それは構造的型付けの方は余計に一手間掛かるという方向の違いだよね。
いずれにせよ名前的型付けにおいて、型の互換性を指示する方法として継承以外のものがあるという点は変わらないと思うけど。
個人的には名前的型付けの型システムに構造的型付けの機能を追加することについては、比較的好意的に捉えているけどね。Rustみたいな言語だとあまり必要性はないのかもしれないけれど、Pythonとかではかなりありがたい。
192デフォルトの名無しさん
2026/09/30(水) 15:09:14.43ID:tj8lvo2G >>191
>型の別名~~名前的型付けと構造的型付けとで違いはないでしょう。
ちょっと脱線してるけど、
(名前的型付け)名前で宣言しないと等価(置換可能)にならない
(構造的型付け)宣言しなくても構造が一緒なら等価(置換可能)
の違いがあるよ。
異なる名前を使っているのなら、
名前的型付けの場合は(名前の等価性を宣言しないと)別物。
構造的型付けの場合は名前ではなく構造を見るから等価性を宣言する必要が無い。
>型の別名~~名前的型付けと構造的型付けとで違いはないでしょう。
ちょっと脱線してるけど、
(名前的型付け)名前で宣言しないと等価(置換可能)にならない
(構造的型付け)宣言しなくても構造が一緒なら等価(置換可能)
の違いがあるよ。
異なる名前を使っているのなら、
名前的型付けの場合は(名前の等価性を宣言しないと)別物。
構造的型付けの場合は名前ではなく構造を見るから等価性を宣言する必要が無い。
193デフォルトの名無しさん
2026/09/30(水) 15:12:41.77ID:l3EYRoUC194デフォルトの名無しさん
2026/09/30(水) 15:42:24.18ID:nOWz/ZAL195デフォルトの名無しさん
2026/09/30(水) 17:01:53.57ID:TLEZAlhX > 娘の足が13.5になったから洗ってしまおうとして
ここから急激に難しくなるよな…
ここから急激に難しくなるよな…
196デフォルトの名無しさん
2026/09/30(水) 17:03:00.56ID:TLEZAlhX 誤爆しましたごめんなさい
ついでと言ってはなんですが解読お願いします
i.imgur.com/rt3L9BV.jpeg
ついでと言ってはなんですが解読お願いします
i.imgur.com/rt3L9BV.jpeg
197デフォルトの名無しさん
2026/09/30(水) 17:24:32.58ID:ynYlHr2f >>191
それはPythonにインターフェースを後付けできないから困っただけで名前的か構造的かは関係ないと思うんだよね
Rustのように後から新たなインターフェースをプリミティブ型に対しても実装できれば十分だよね
その件でも構造的型付けは不要だよ
// Rustはtraitがインタフェース相当
trait Hello {
fn hello(&self);
}
// 既存の数値型i32にHelloを実装
impl Hello for i32 {
fn hello(&self) {
println!("Hello! {self}");
}
}
// 既存の文字列型strにHelloを実装
impl Hello for str {
fn hello(&self) {
println!("Hello! {self}");
}
}
fn main() {
123.hello();
"abc".hello();
}
// 実行結果
// Hello! 123
// Hello! abc
それはPythonにインターフェースを後付けできないから困っただけで名前的か構造的かは関係ないと思うんだよね
Rustのように後から新たなインターフェースをプリミティブ型に対しても実装できれば十分だよね
その件でも構造的型付けは不要だよ
// Rustはtraitがインタフェース相当
trait Hello {
fn hello(&self);
}
// 既存の数値型i32にHelloを実装
impl Hello for i32 {
fn hello(&self) {
println!("Hello! {self}");
}
}
// 既存の文字列型strにHelloを実装
impl Hello for str {
fn hello(&self) {
println!("Hello! {self}");
}
}
fn main() {
123.hello();
"abc".hello();
}
// 実行結果
// Hello! 123
// Hello! abc
198デフォルトの名無しさん
2026/09/30(水) 17:34:12.29ID:BI+U5C/y 構造的型付けはビルド時に勝手にコンパイラが適応出来る場合にやってくれればいいだけで
マは名前的で全部やってればいいんだよ
マは名前的で全部やってればいいんだよ
199デフォルトの名無しさん
2026/09/30(水) 18:07:31.38ID:1evedIxZ >>197
その例だとRustはもっと楽ができるぜ
実装コードがどれも同じなのでジェネリックにこれだけだ
impl<T: std::fmt::Display> Hello for T {
fn hello(&self) {
println!("Hello! {self}");
}
}
ちなみにprintは表示が可能な型が来ないと静的にエラーにしてくれる
それゆえ表示が可能な型=Displayトレイト境界を与えてる
その例だとRustはもっと楽ができるぜ
実装コードがどれも同じなのでジェネリックにこれだけだ
impl<T: std::fmt::Display> Hello for T {
fn hello(&self) {
println!("Hello! {self}");
}
}
ちなみにprintは表示が可能な型が来ないと静的にエラーにしてくれる
それゆえ表示が可能な型=Displayトレイト境界を与えてる
200デフォルトの名無しさん
2026/09/30(水) 18:50:04.21ID:b6zJjgmk201デフォルトの名無しさん
2026/09/30(水) 18:56:30.45ID:nOWz/ZAL202デフォルトの名無しさん
2026/09/30(水) 18:57:13.16ID:nOWz/ZAL 176じゃない、>>178だわ。
203デフォルトの名無しさん
2026/09/30(水) 18:57:44.48ID:hDdnjb0Z204デフォルトの名無しさん
2026/09/30(水) 19:11:02.23ID:tj8lvo2G >>194
部分型は基本的に反対称律を持つから同値関係じゃなくて(半)順序関係だよ。
「L1はUの別名、L2はUの別名」としたとき、L1とL2は同じUだから置換できるけど、
「L1はUの部分型、L2はUの部分型」としたとき、L1とL2は同じかどうかわからないから(L1、L2として)置換できるかもしれないしできないかもしれない。
部分型は基本的に反対称律を持つから同値関係じゃなくて(半)順序関係だよ。
「L1はUの別名、L2はUの別名」としたとき、L1とL2は同じUだから置換できるけど、
「L1はUの部分型、L2はUの部分型」としたとき、L1とL2は同じかどうかわからないから(L1、L2として)置換できるかもしれないしできないかもしれない。
205デフォルトの名無しさん
2026/09/30(水) 19:20:06.95ID:nOWz/ZAL >>171がどういう意味で継承を使ったのかは本人に聞いてみないと分からないが、自分は「型システム上の部分型関係を作ることを目的とした構文」くらいの意味で使っているけど。
構造的型付けの主な強みは、明示的な継承構文を使わなくても部分型関係が作れるところにあって、明示的な継承構文を使わないと部分型関係が作れない言語では構造的型付けの機能があると重宝する。ただ、Rustのトレイトみたいな機能がある場合は、既存の型に手を加えずに互換性のある型を定義するという同じことができるので、構造的型付けの強みは大幅に減殺される……というイメージ。
構造的型付けの主な強みは、明示的な継承構文を使わなくても部分型関係が作れるところにあって、明示的な継承構文を使わないと部分型関係が作れない言語では構造的型付けの機能があると重宝する。ただ、Rustのトレイトみたいな機能がある場合は、既存の型に手を加えずに互換性のある型を定義するという同じことができるので、構造的型付けの強みは大幅に減殺される……というイメージ。
206デフォルトの名無しさん
2026/09/30(水) 19:30:57.77ID:nOWz/ZAL207デフォルトの名無しさん
2026/09/30(水) 20:40:38.21ID:tWodc6AH Pythonで開発している人たちによるPythonのProtocolについての説明記事を見ると
仕様を勧めないとか積極的に使わないと書かれてる
理由は構造的型付けだから
具体的にはProtocol名を用いて定義しないため分かりにくい可読性が低い保守性が低い
構造的に同じものが他にあると混乱する誤作動する安全でない
メリットよりデメリットの方が上回る
仕様を勧めないとか積極的に使わないと書かれてる
理由は構造的型付けだから
具体的にはProtocol名を用いて定義しないため分かりにくい可読性が低い保守性が低い
構造的に同じものが他にあると混乱する誤作動する安全でない
メリットよりデメリットの方が上回る
208デフォルトの名無しさん
2026/09/30(水) 21:03:37.11ID:STDSw+Ki 可読性w
保守性w
童貞が女の口説き方教えてくれとるわw
保守性w
童貞が女の口説き方教えてくれとるわw
209デフォルトの名無しさん
2026/09/30(水) 21:03:39.43ID:HDRjBBba 構造的型付けはProtocol名を用いて記述しなくても指定の構造さえ記述すれば済むというメリットがある!
と言いたいところだがそれを上回るデメリットを引き連れてしまうよな
構造的型付けを採用する言語が少ないのも仕方ないか
と言いたいところだがそれを上回るデメリットを引き連れてしまうよな
構造的型付けを採用する言語が少ないのも仕方ないか
210デフォルトの名無しさん
2026/09/30(水) 21:37:52.93ID:TLEZAlhX >>207
Protocolは実行時にメソッドがなくてエラーになってたのを
型チェッカーで実行前に洗い出せるようになるよってものなので
君が言うところの型安全wにはなると思うけどねえ
大きなメリットじゃないか
Protocolは実行時にメソッドがなくてエラーになってたのを
型チェッカーで実行前に洗い出せるようになるよってものなので
君が言うところの型安全wにはなると思うけどねえ
大きなメリットじゃないか
211デフォルトの名無しさん
2026/09/30(水) 21:39:57.81ID:TLEZAlhX >>209
TypeScriptもPythonも動的型付けによるダックタイピングとの相性を考えて構造的型付けを採用してるわけ
少なくともTypeScriptやPythonではメリットの方が大きいと判断されてるというのは理解しようよ
TypeScriptもPythonも動的型付けによるダックタイピングとの相性を考えて構造的型付けを採用してるわけ
少なくともTypeScriptやPythonではメリットの方が大きいと判断されてるというのは理解しようよ
212デフォルトの名無しさん
2026/09/30(水) 21:40:49.47ID:tj8lvo2G >>205
継承についてはちょっと違って、
名前的型付けで上位型−部分型の関係を構成する方法
ということで「名前的型付け」がポイント。
構造的型付けの強みは表記の話もあるけど、それよりも「実際に部分型にするまで部分型を用意する必要がない」という設計上の柔軟性。
Rustは使ってないので間違えているかもしれないけど、拡張トレイトやジェネリックは動的多態できないし、トレイトオブジェクトはスーパートレイトを取り込む必要があるので「大幅に減殺される」という感じは無いなぁ。
継承についてはちょっと違って、
名前的型付けで上位型−部分型の関係を構成する方法
ということで「名前的型付け」がポイント。
構造的型付けの強みは表記の話もあるけど、それよりも「実際に部分型にするまで部分型を用意する必要がない」という設計上の柔軟性。
Rustは使ってないので間違えているかもしれないけど、拡張トレイトやジェネリックは動的多態できないし、トレイトオブジェクトはスーパートレイトを取り込む必要があるので「大幅に減殺される」という感じは無いなぁ。
213デフォルトの名無しさん
2026/09/30(水) 21:42:47.99ID:nOWz/ZAL Qiitaのこの記事? 「Pythonのtyping.ProtocolとABCの違いと実務的な考察」(https://qiita.com/sagong_ryung/items/140cc8ea35157fd184f5)
個人の見解みたいだけど、「人たち」による別の記事もあるのかな?
ちなみに、『ロバストPython』という本の13章(といっても10ページ程度)にProtocolについて分かりやすい説明がある。公式リファレンス以外の解説としては、個人的にはこちらの方を勧めたいかな。
自分は正直、上記のQiita記事があまり説得的とは感じないけど(もっとも、外部ライブラリや既存コードで使うのが良いとする点は妥当だろう)、個人の感想はいろいろだからね。推奨しないという人も居るんでしょう。
個人の見解みたいだけど、「人たち」による別の記事もあるのかな?
ちなみに、『ロバストPython』という本の13章(といっても10ページ程度)にProtocolについて分かりやすい説明がある。公式リファレンス以外の解説としては、個人的にはこちらの方を勧めたいかな。
自分は正直、上記のQiita記事があまり説得的とは感じないけど(もっとも、外部ライブラリや既存コードで使うのが良いとする点は妥当だろう)、個人の感想はいろいろだからね。推奨しないという人も居るんでしょう。
214デフォルトの名無しさん
2026/09/30(水) 21:43:07.80ID:ha6ZVeNk 静的型付け言語にはメリットがないという主張なのね
215デフォルトの名無しさん
2026/09/30(水) 21:48:50.17ID:ebQsnRA1 >>212
貴方が動的多態の意味を勘違いしている
貴方が動的多態の意味を勘違いしている
216デフォルトの名無しさん
2026/09/30(水) 21:59:42.03ID:DgqfE3x6 >>215
具体的には?
具体的には?
217デフォルトの名無しさん
2026/09/30(水) 23:16:27.83ID:ZN730fJJ >>201
>テンプレートとかRustのトレイトとか挙げてるやん。
その2つはどっちも反例になってないでしょ
テンプレートは名前的型付けじゃないしRustのトレイトはインターフェース継承と同じで定義を継承してる
>テンプレートとかRustのトレイトとか挙げてるやん。
その2つはどっちも反例になってないでしょ
テンプレートは名前的型付けじゃないしRustのトレイトはインターフェース継承と同じで定義を継承してる
218デフォルトの名無しさん
2026/09/30(水) 23:18:24.05ID:Tf9baifh >>212
>>拡張トレイトやジェネリックは動的多態できないし、
Rustは拡張トレイトも静的ディスパッチと動的ディスパッチの両方できる
ジェネリックはC++でもRustでも静的ディスパッチで単相化するための文法
Rustではジェネリックにせずとも可能
普通の関数で静的ディスパッチと動的ディスパッチそれぞれを選んでどちらも使える
そんな至れり尽くせりの言語は他にないでしょう
>>トレイトオブジェクトはスーパートレイトを取り込む必要がある
Rustはスーパートレイトも含めてどれだけ大量のトレイトを指定しても静的に一つのvtableに取り込むことができるため柔軟性があるとともに動的ディスパッチが最も速い、が正解
これができない言語は複数のvtableを動的に見ていくことになって遅い
>>拡張トレイトやジェネリックは動的多態できないし、
Rustは拡張トレイトも静的ディスパッチと動的ディスパッチの両方できる
ジェネリックはC++でもRustでも静的ディスパッチで単相化するための文法
Rustではジェネリックにせずとも可能
普通の関数で静的ディスパッチと動的ディスパッチそれぞれを選んでどちらも使える
そんな至れり尽くせりの言語は他にないでしょう
>>トレイトオブジェクトはスーパートレイトを取り込む必要がある
Rustはスーパートレイトも含めてどれだけ大量のトレイトを指定しても静的に一つのvtableに取り込むことができるため柔軟性があるとともに動的ディスパッチが最も速い、が正解
これができない言語は複数のvtableを動的に見ていくことになって遅い
219デフォルトの名無しさん
2026/10/01(木) 00:27:33.58ID:yqAKIueN Rubyをdisるのはよせ
220デフォルトの名無しさん
2026/10/01(木) 01:03:03.52ID:MoFt4NQA >>217
継承という語は、一般に部分型関係を作ることを目的とする構文という意味で使われるが、Rustのトレイトは部分型関係を作るものではない。一般的にもRustのトレイトが継承であるとは説明されない。
C/C++のテンプレートやPythonのプロトコルなんかを一種の構造的な型として観念する考え方は個人的には結構好きだが、言語仕様としての型(これらの言語において通常の意味での型とされる名前付きの型)と同様の扱いがされるわけではない。テンプレートが構造的型付け「に近い」とか、構造的型付け「的」とか、「一種の」構造的型付けといった、ちょっと含みのある表現で説明されることが多いのはなぜかを考えてみるとよい。
大体、そんなオレオレ定義・解釈を前提に「名前的型付けには型の互換性を指定する方法が継承しかない。だから、構造的型付けの方が優れている」とやっても誰も聞いてくれないでしょ。名前的型付けと構造的型付けの比較の文脈で、「テンプレートは構造的型付けだから構造的型付けの方が優れている」と主張することがどれだけ無意味か考えてみたら分かりそうなものだが。そんなことをしなくても構造的型付けには一定の価値は認められているよ。
継承という語は、一般に部分型関係を作ることを目的とする構文という意味で使われるが、Rustのトレイトは部分型関係を作るものではない。一般的にもRustのトレイトが継承であるとは説明されない。
C/C++のテンプレートやPythonのプロトコルなんかを一種の構造的な型として観念する考え方は個人的には結構好きだが、言語仕様としての型(これらの言語において通常の意味での型とされる名前付きの型)と同様の扱いがされるわけではない。テンプレートが構造的型付け「に近い」とか、構造的型付け「的」とか、「一種の」構造的型付けといった、ちょっと含みのある表現で説明されることが多いのはなぜかを考えてみるとよい。
大体、そんなオレオレ定義・解釈を前提に「名前的型付けには型の互換性を指定する方法が継承しかない。だから、構造的型付けの方が優れている」とやっても誰も聞いてくれないでしょ。名前的型付けと構造的型付けの比較の文脈で、「テンプレートは構造的型付けだから構造的型付けの方が優れている」と主張することがどれだけ無意味か考えてみたら分かりそうなものだが。そんなことをしなくても構造的型付けには一定の価値は認められているよ。
221デフォルトの名無しさん
2026/10/01(木) 01:03:52.45ID:AJ//+KV9 オブジェクト指向で抽象メソッド/仮想メソッドを使うと便利でわかりやすくなるけど
実行が遅くなるため面倒でわかりにくい方法を選ぶ
という本末転倒な言語が存在する現実があるもんな
便利かつ速いの両立は重要
実行が遅くなるため面倒でわかりにくい方法を選ぶ
という本末転倒な言語が存在する現実があるもんな
便利かつ速いの両立は重要
222デフォルトの名無しさん
2026/10/01(木) 01:15:57.35ID:S1m1fK+S >>220
その通り
2種類の構造的型付けの用法がそこでなされていることに注目
1つ目は本来の構造的型付けで
「構造的に同じオブジェクトが同じ型とみなされ動く」
2つ目は構造的型付けではなく
「『あるメソッド』または『あるフィールド変数』が使われている関数では、それらを持つオブジェクトが動き、持たないオブジェクトはエラー」
ようするにダックタイピングであり構造的型付けとは明白に異なる
その通り
2種類の構造的型付けの用法がそこでなされていることに注目
1つ目は本来の構造的型付けで
「構造的に同じオブジェクトが同じ型とみなされ動く」
2つ目は構造的型付けではなく
「『あるメソッド』または『あるフィールド変数』が使われている関数では、それらを持つオブジェクトが動き、持たないオブジェクトはエラー」
ようするにダックタイピングであり構造的型付けとは明白に異なる
223デフォルトの名無しさん
2026/10/01(木) 01:35:40.22ID:rHwutQT4 小さなプログラムではダックタイピングもお手軽で良いものだ
しかし大きなプログラムでは足を引っ張る存在になる
通過条件を名前で明瞭に指定できる方が好ましい
単純な例
関数fを通過できるxはhello()とbye()を持っていなければならないとすぐにわかるが
これがもっと大量に多段に複雑になると見通せなくなる
function f(x) {
f1(x)
f2(x)
}
function f1(x) {
x.hello()
}
function f2(x) {
x.bye()
}
しかし大きなプログラムでは足を引っ張る存在になる
通過条件を名前で明瞭に指定できる方が好ましい
単純な例
関数fを通過できるxはhello()とbye()を持っていなければならないとすぐにわかるが
これがもっと大量に多段に複雑になると見通せなくなる
function f(x) {
f1(x)
f2(x)
}
function f1(x) {
x.hello()
}
function f2(x) {
x.bye()
}
224デフォルトの名無しさん
2026/10/01(木) 08:15:19.04ID:qDprx/3L fなんて名前つけてるからわかりにくいだけ
225デフォルトの名無しさん
2026/10/01(木) 08:46:43.48ID:y+q+mooV226デフォルトの名無しさん
2026/10/01(木) 09:32:32.19ID:7cmToZJY227デフォルトの名無しさん
2026/10/01(木) 09:40:05.10ID:jv3WtkyP >>220
テンプレートが名前的型付けじゃないことはわかったみたいだね
>Rustのトレイトは部分型関係を作るものではない
Rustのトレイトは部分型関係を作るためのものだよ
というかそのために存在してる
impl MyTrait For MyStructという宣言は
MyStructという型とimpl MyTrait/dyn MyTraitという型との部分型関係を作るもの
>だから、構造的型付けの方が優れている
これは曲解だね
俺はそんなこと全く思ってない
それぞれの特徴を理解して使い分ければいいだけ
最初に継承しかないと書いた人の意図は知らんけど
テンプレートが名前的型付けじゃないことはわかったみたいだね
>Rustのトレイトは部分型関係を作るものではない
Rustのトレイトは部分型関係を作るためのものだよ
というかそのために存在してる
impl MyTrait For MyStructという宣言は
MyStructという型とimpl MyTrait/dyn MyTraitという型との部分型関係を作るもの
>だから、構造的型付けの方が優れている
これは曲解だね
俺はそんなこと全く思ってない
それぞれの特徴を理解して使い分ければいいだけ
最初に継承しかないと書いた人の意図は知らんけど
228デフォルトの名無しさん
2026/10/01(木) 09:46:02.53ID:y+q+mooV229デフォルトの名無しさん
2026/10/01(木) 09:47:26.94ID:jv3WtkyP >>225
拡張トレイトがExtention Traitの日本語訳ということなら
既存の構造体を拡張するのに新しくMyTraitを定義して
impl MyTrait for ForeignStructとすることで
ForeignStructに新しいメソッドを生やす手法のこと
拡張トレイトがExtention Traitの日本語訳ということなら
既存の構造体を拡張するのに新しくMyTraitを定義して
impl MyTrait for ForeignStructとすることで
ForeignStructに新しいメソッドを生やす手法のこと
230デフォルトの名無しさん
2026/10/01(木) 09:58:18.59ID:7cmToZJY >>227
C++のテンプレートは、それ自体としては名前的型付けでも構造的型付けでもないぞ。テンプレートによって観念される構造的な型を言語仕様上の型(C++における通常の型)と見てよいなら構造的型付けといってもよいが、C++の仕様はそうなっていない。
Rustのトレイトは部分型関係を作るというオレオレ定義がやりたいならどうぞご自由に。検索するなりAIに聞くなりして、Rustのトレイトは継承か、部分型関係を作るか、サブタイピング多相の一種かと聞いてみたらよいのに。
C++のテンプレートは、それ自体としては名前的型付けでも構造的型付けでもないぞ。テンプレートによって観念される構造的な型を言語仕様上の型(C++における通常の型)と見てよいなら構造的型付けといってもよいが、C++の仕様はそうなっていない。
Rustのトレイトは部分型関係を作るというオレオレ定義がやりたいならどうぞご自由に。検索するなりAIに聞くなりして、Rustのトレイトは継承か、部分型関係を作るか、サブタイピング多相の一種かと聞いてみたらよいのに。
231デフォルトの名無しさん
2026/10/01(木) 10:56:31.63ID:yO5/bCLS >>222
これぞ複オジメソッド!
これぞ複オジメソッド!
232デフォルトの名無しさん
2026/10/01(木) 11:25:38.07ID:jiVxewCN233デフォルトの名無しさん
2026/10/01(木) 11:30:35.71ID:ZKWfJGw+ 具体的に>>197のtrait Helloの例を考えてみると
i32型はHelloの部分型になったと解釈することは可能で
str型もHelloの部分型になったと解釈することは可能であるが
問題はHelloを定義もしくはuse パス::Hello;したモジュール空間でしか部分型の関係が有効でないという点だ
つまりi32型が本質的にHelloの部分型になったとは言えない
このようにRustのtraitは柔軟性が高くて従来の枠組みで解釈しにくい
i32型はHelloの部分型になったと解釈することは可能で
str型もHelloの部分型になったと解釈することは可能であるが
問題はHelloを定義もしくはuse パス::Hello;したモジュール空間でしか部分型の関係が有効でないという点だ
つまりi32型が本質的にHelloの部分型になったとは言えない
このようにRustのtraitは柔軟性が高くて従来の枠組みで解釈しにくい
234デフォルトの名無しさん
2026/10/01(木) 11:33:58.57ID:jiVxewCN 「Rustのトレイトは部分型関係を作るためのものだよ
というかそのために存在してる」
複クン語録がまたひとつ増えたな
というかそのために存在してる」
複クン語録がまたひとつ増えたな
235デフォルトの名無しさん
2026/10/01(木) 11:40:20.09ID:ZKWfJGw+ >>234
Rustのトレイトを実装するとその型はそのトレイトの部分型関係になるのは事実
ただし有効範囲がそのトレイトの利用を宣言した範囲のみ
だからどちらも正しい
「本質的に部分型になったわけではない」
「その空間では部分型になっている」
Rustのトレイトを実装するとその型はそのトレイトの部分型関係になるのは事実
ただし有効範囲がそのトレイトの利用を宣言した範囲のみ
だからどちらも正しい
「本質的に部分型になったわけではない」
「その空間では部分型になっている」
236デフォルトの名無しさん
2026/10/01(木) 12:00:46.25ID:ZKWfJGw+ つまりRustは既存のコードに全く影響を与えることなく
自分の空間内で新たな抽象型(trait)を導入して既存の型をその部分型にすることが可能
という柔軟性を持っていることになる
自分の空間内で新たな抽象型(trait)を導入して既存の型をその部分型にすることが可能
という柔軟性を持っていることになる
237デフォルトの名無しさん
2026/10/01(木) 14:13:08.24ID:JSml55T0 crate A の trait を
crate B の struct に
実装したいんだが
crate B の struct に
実装したいんだが
238デフォルトの名無しさん
2026/10/01(木) 14:31:53.80ID:ZHX7JAyA239デフォルトの名無しさん
2026/10/01(木) 15:25:10.43ID:J4R8nJl4 自由度を失ってる
240デフォルトの名無しさん
2026/10/01(木) 15:39:28.93ID:hkcHmRg+ 自由度ってなんだ?
何が失われている?
何が失われている?
241デフォルトの名無しさん
2026/10/02(金) 10:35:58.17ID:3EJYfiDQ 拡張メソッドはオブジェクト指向なのか?
242デフォルトの名無しさん
2026/10/02(金) 11:51:55.08ID:7hPXzRqp >>197の例は既存のi32型のオブジェクトとstr型のオブジェクトが共にHelloという抽象型オブジェクトとしても扱えるようになった
オブジェクト指向プログラミングの利点の一つであるコードの共通化が可能になった
例えば抽象型Helloを受け付ける関数
fn hello_twice(x: impl Hello) {
x.hello();
x.hello();
}
共通してi32型もstr型もどちらも使える
hello_twice(123);
hello_twice("abc");
オブジェクト指向プログラミングの利点の一つであるコードの共通化が可能になった
例えば抽象型Helloを受け付ける関数
fn hello_twice(x: impl Hello) {
x.hello();
x.hello();
}
共通してi32型もstr型もどちらも使える
hello_twice(123);
hello_twice("abc");
243デフォルトの名無しさん
2026/10/02(金) 12:06:22.86ID:YK3IsGy0 >>241
メソッドがすでにオブジェクト指向
メソッドがすでにオブジェクト指向
244デフォルトの名無しさん
2026/10/02(金) 12:18:35.18ID:JhD5xoM2245デフォルトの名無しさん
2026/10/02(金) 13:31:59.98ID:poUMNNer そんな悪手教えんなよ
246デフォルトの名無しさん
2026/10/02(金) 13:43:28.24ID:3EJYfiDQ247デフォルトの名無しさん
2026/10/02(金) 15:32:01.06ID:3B7GzgLW248デフォルトの名無しさん
2026/10/02(金) 15:32:33.29ID:FvujYSRB use v5.38;
use feature 'class';
no warnings 'experimental::class';
class Hello {
field $x :param;
method hello_twice {
say "Hello! $x";
}
}
Hello->new(x => 123)->hello_twice;
Hello->new(x => 'abc')->hello_twice;
実行結果
$ perl hello_twice.txt
Hello! 123
Hello! abc
use feature 'class';
no warnings 'experimental::class';
class Hello {
field $x :param;
method hello_twice {
say "Hello! $x";
}
}
Hello->new(x => 123)->hello_twice;
Hello->new(x => 'abc')->hello_twice;
実行結果
$ perl hello_twice.txt
Hello! 123
Hello! abc
249デフォルトの名無しさん
2026/10/02(金) 15:37:47.92ID:FvujYSRB やっぱClassなど使わん方がすっきり書けるな
use v5.38;
package Hello {
sub new ($class, $x) { bless \$x, $class }
sub hello_twice ($self) { say "Hello! $$self" }
}
Hello->new(123)->hello_twice;
Hello->new('abc')->hello_twice;
use v5.38;
package Hello {
sub new ($class, $x) { bless \$x, $class }
sub hello_twice ($self) { say "Hello! $$self" }
}
Hello->new(123)->hello_twice;
Hello->new('abc')->hello_twice;
250デフォルトの名無しさん
2026/10/02(金) 16:18:06.08ID:FvujYSRB use v5.38;
sub Hello ($x) {
sub { say "Hellow! $x" }
}
Hello(123)->();
Hello("abc")->();
sub Hello ($x) {
sub { say "Hellow! $x" }
}
Hello(123)->();
Hello("abc")->();
251デフォルトの名無しさん
2026/10/02(金) 17:40:59.76ID:XTYJpt71 意図が全く伝わってなくて芝生える
252デフォルトの名無しさん
2026/10/02(金) 18:25:06.64ID:FvujYSRB うん、書いてて俺もそう思った
253デフォルトの名無しさん
2026/10/02(金) 19:44:57.95ID:+L4zhpGG hello_twice()は2回helloだよ
254デフォルトの名無しさん
2026/10/02(金) 19:57:02.54ID:+L4zhpGG >>244
そのHelloは抽象型
From/Intoは具象型同士の変換だよ
ではどうすればよいか?
二つの方法があります
一つ目は既に>>242に出ているimpl Helloで受け取る方法
fn hello_twice(x: impl Hello) {
x.hello();
x.hello();
}
これは単相化されて静的ディスパッチつまり普通の関数呼び出しになる
そのためインライン化などの最適化も行なえるから最も有利だね
呼び出す側は既に出ているようにそのまま渡せる
hello_twice(123);
hello_twice("abc");
これは値をそのまま渡しているけど
受け取り側をx: &impl Helloにすることで参照を渡すこともできるよ
そのHelloは抽象型
From/Intoは具象型同士の変換だよ
ではどうすればよいか?
二つの方法があります
一つ目は既に>>242に出ているimpl Helloで受け取る方法
fn hello_twice(x: impl Hello) {
x.hello();
x.hello();
}
これは単相化されて静的ディスパッチつまり普通の関数呼び出しになる
そのためインライン化などの最適化も行なえるから最も有利だね
呼び出す側は既に出ているようにそのまま渡せる
hello_twice(123);
hello_twice("abc");
これは値をそのまま渡しているけど
受け取り側をx: &impl Helloにすることで参照を渡すこともできるよ
255デフォルトの名無しさん
2026/10/02(金) 20:24:52.90ID:Ei5gJ0Kk もう一つの方法は&dyn Helloで受け取る方法
fn hello_twice2(x: &dyn Hello) {
x.hello();
x.hello();
}
これは動的ディスパッチになる
dynはもちろん動的の略
>>254の単相化とは異なりこの関数の実体が一つになることがメリット
呼び出しは引数のサイズを揃えないといけないから参照で渡す
hello_twice2(&123);
hello_twice2(&"abc");
そのため受け取り側も&が付いてx: &dyn Helloになってるよ
しかし動的ディスパッチは実行時にvtableを引くため遅いうえに
インライン最適化ができないためかなり遅い
それでもdyn Helloにしかできない魅力もある分かるよね
fn hello_twice2(x: &dyn Hello) {
x.hello();
x.hello();
}
これは動的ディスパッチになる
dynはもちろん動的の略
>>254の単相化とは異なりこの関数の実体が一つになることがメリット
呼び出しは引数のサイズを揃えないといけないから参照で渡す
hello_twice2(&123);
hello_twice2(&"abc");
そのため受け取り側も&が付いてx: &dyn Helloになってるよ
しかし動的ディスパッチは実行時にvtableを引くため遅いうえに
インライン最適化ができないためかなり遅い
それでもdyn Helloにしかできない魅力もある分かるよね
256デフォルトの名無しさん
2026/10/02(金) 21:58:35.67ID:/09UbK/K やりたいことに対して一番パーフォーマンスが出るものでやればよい
再利用なんてする必要もなくなった
再利用なんてする必要もなくなった
257デフォルトの名無しさん
2026/10/02(金) 22:25:44.89ID://P+TiQT 動的ディスパッチのdyn Helloを使うのは実行時ガチャな時だな
どの具体型が返ってくるかわからないガチャ関数やガチャ式
あとはベクタ等へ混在して突っ込んで要素が実行時ガチャになる時
焦点はそこじゃなくてほとんどのプログラミング言語は抽象型の抽象メソッドが動的ディスパッチになって遅くなることだろ
一方でRustはガチャでなければdyn Helloをimpl Helloに変えるだけで静的ディスパッチになってインライン最適化も起きて劇的に速くなる
どの具体型が返ってくるかわからないガチャ関数やガチャ式
あとはベクタ等へ混在して突っ込んで要素が実行時ガチャになる時
焦点はそこじゃなくてほとんどのプログラミング言語は抽象型の抽象メソッドが動的ディスパッチになって遅くなることだろ
一方でRustはガチャでなければdyn Helloをimpl Helloに変えるだけで静的ディスパッチになってインライン最適化も起きて劇的に速くなる
258デフォルトの名無しさん
2026/10/02(金) 22:44:01.04ID:kTuJA86n 仮想メソッドは動的ディスパッチになって遅くなるから使うな!
という本末転倒の流儀まであるから草生える
という本末転倒の流儀まであるから草生える
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 【野球】侍ジャパン、韓国に快勝し優勝! 大会3連覇 西川先制弾、正木4戦連発、先発の高橋は7回1失点と好投 アジアCS [冬月記者★]
- 安倍晋三元首相の銅像建立 東郷神社で除幕式 昭恵さんら参列 福岡・福津 (産経) [少考さん★]
- 消費減税、効果小さい63% 財源、支援金説明必要85%-共同通信世論調査 ★2 [蚤の市★]
- 【音楽】スピッツのドラム・﨑山龍男、交通事故で救急搬送 「命に別状はないものの、全身を強く打っており」 [Ailuropoda melanoleuca★]
- 【セルジオ越後】ブラジルに勝ったけどそれで世界の強豪に肩を並べたと思ったら大間違い。ヴィニシウスのようなスターもいない★2 [jinjin★]
- 【芸能】小泉今日子、クマ被害対策でドングリの木3000本植樹 「口だけではダメ」自ら行動し高まる“政治家転身”への期待★2 [冬月記者★]
- 今日床屋さん行ったんやけどハゲにされてたんやが🥺
- 【緊急】絶対にやるべきギャルゲーやノベルゲーを教えてほしい
- さっさと死ねよ馬鹿ネカマキモ脛毛👊😅👊🏡
- 【悲惨】日本人の81%「日本は真面目に頑張って働いてる普通の人が十分報われない」 実際、年収330万円〜870万円の世帯で可処分所得が激減 [597533159]
- ぼっちざろっくの喜多郁代ちゃんの足を舐めたい
- 【悲報】肉フェスさん、半分冷凍の肉が2100円で炎上wwwwwwwwwwwwwwwwwwwwwww