探検


オブジェクト指向はオワコン? part4

2026/10/01(木) 14:13:08.24ID:JSml55T0
crate A の trait を
crate B の struct に
実装したいんだが
2026/10/01(木) 14:31:53.80ID:ZHX7JAyA
>>237
それは既存コードに影響を与えるから直接の実装は禁止されている
ラッピングして自分の型にして実装できる
2026/10/01(木) 15:25:10.43ID:J4R8nJl4
自由度を失ってる
2026/10/01(木) 15:39:28.93ID:hkcHmRg+
自由度ってなんだ?
何が失われている?
241デフォルトの名無しさん
垢版 |
2026/10/02(金) 10:35:58.17ID:3EJYfiDQ
拡張メソッドはオブジェクト指向なのか?
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");
2026/10/02(金) 12:06:22.86ID:YK3IsGy0
>>241
メソッドがすでにオブジェクト指向
2026/10/02(金) 12:18:35.18ID:JhD5xoM2
>>242
HelloにFrom<i32>とFrom<&str>と
i32にInto<Hello>と
&strにInto<Hello>も実装するんやで
2026/10/02(金) 13:31:59.98ID:poUMNNer
そんな悪手教えんなよ
246デフォルトの名無しさん
垢版 |
2026/10/02(金) 13:43:28.24ID:3EJYfiDQ
>>243
メソッドと拡張メソッドは違うでしょうに
拡張メソッドはオブジェクト指向として邪道なのでは?
2026/10/02(金) 15:32:01.06ID:3B7GzgLW
>>246
拡張メソッド ⊆ メソッド

なぜオブジェクト指向としては邪道だと思うの?
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
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;
2026/10/02(金) 16:18:06.08ID:FvujYSRB
use v5.38;
sub Hello ($x) {
 sub { say "Hellow! $x" }
}
Hello(123)->();
Hello("abc")->();
2026/10/02(金) 17:40:59.76ID:XTYJpt71
意図が全く伝わってなくて芝生える
2026/10/02(金) 18:25:06.64ID:FvujYSRB
うん、書いてて俺もそう思った
2026/10/02(金) 19:44:57.95ID:+L4zhpGG
hello_twice()は2回helloだよ
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にすることで参照を渡すこともできるよ
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にしかできない魅力もある分かるよね
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に変えるだけで静的ディスパッチになってインライン最適化も起きて劇的に速くなる
2026/10/02(金) 22:44:01.04ID:kTuJA86n
仮想メソッドは動的ディスパッチになって遅くなるから使うな!
という本末転倒の流儀まであるから草生える
2026/10/02(金) 22:44:51.68ID:+vRC15PC
これ>>256
人間が小さなワーキングメモリで考えやすく書きやすいように
人工的に小さく区切って部品化する必要がなくなってる

しかしAIなら多少区切りを大きく出来るとは言え完全になくすことは出来ないけど
2026/10/02(金) 22:55:13.49ID:Qvuvq1PR
>>256
パーフォーマンスが出る静的ディスパッチを選べない言語では、パーフォーマンスを断念するか、オブジェクト指向による抽象化を断念するかの二者択一になることがある
2026/10/02(金) 23:18:34.58ID:OeRsxfuS
>>256
再利用ではなくて抽象型オブジェクトによるコードの共通化が必須
コードの読みやすさやメンテのしやすさがまるで違ってくる
262デフォルトの名無しさん
垢版 |
2026/10/02(金) 23:53:31.23ID://P+TiQT
C++はテンプレート使えば単相化静的ディスパッチになるけど
抽象型名を伴わない静的ダックタイピングな点や仮想関数による動的ディスパッチの時とコードが全く違ってくる点が残念だよな
Rustはトレイトの仮想関数そのまま静的ディスパッチと動的ディスパッチを簡単に切り替えられる点が大きい
2026/10/03(土) 06:24:49.57ID:MKfZz3zJ
何言ってるのかよく分からない
#include <concepts>
void hello_twice(std::derived_from<Hello> auto* x) {
x->hello();
x->hello();
}
でstd::derived_from<T, Hello>な型Tがfinalなら静的ディスパッチ、じゃなければ動的
264デフォルトの名無しさん
垢版 |
2026/10/03(土) 11:11:33.42ID:DkMxwAWo
動的ディスパッチが許されるのはメモリにメッセージをキューするときだけ
xをそれぞれのhellohelloのキューバッファにプッシュするときだけだ
265デフォルトの名無しさん
垢版 |
2026/10/03(土) 11:14:22.71ID:DkMxwAWo
上の例で言えばfinal以外は害悪
つまり継承は害悪
266デフォルトの名無しさん
垢版 |
2026/10/03(土) 12:23:02.61ID:iBT1FpbZ
>>263
finalでなければ動的ディスパッチされる点でC++は敗北している
Rustとの違いが分かったかい?
2026/10/03(土) 23:40:59.92ID:IsyLBp27
そもそも既存のプリミティブ型を
>>197のように自分で作ったHello抽象型に属させることが出来ない言語と出来る言語があるような気がする
268デフォルトの名無しさん
垢版 |
2026/10/03(土) 23:58:48.84ID:Oxr6SIY+
>>248は面白いぞ
数値型や文字列型をHelloの子供にする話なのにフィールドに入れてる
269デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:16:08.78ID:5zMvmFAt
>>268
どうして数値をhelloの子どもにするんです?
オブジェクト指向ではないと思います
270デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:18:31.31ID:5zMvmFAt
拡張メソッドは拡張にメソッドが生えてるだけでオブジェクトメソッドではない、オブジェクト指向において拡張メソッドは絶対悪
271デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:19:56.81ID:5zMvmFAt
スタティックメソッドもオブジェクト指向ではない
272デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:29:37.00ID:kMiXBIQP
オブジェクト指向の目的はカプセル化とコードの共通化
後者は異なる型に対して同じメソッド名で共通に呼べる多相性により実現される
273デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:31:13.65ID:kMiXBIQP
具体的には例えば異なる具象型Aと具象型Bを一つの抽象型Xに所属させることで共通のメソッドを使えるようにする
これによりコードの共通化が実現される
274デフォルトの名無しさん
垢版 |
2026/10/04(日) 03:34:06.17ID:kMiXBIQP
抽象型Xの実現方法は各プログラミング言語それぞれの方法で構わない
たとえばクラスを用いる場合やインターフェースを用いる場合など各言語に適した方法が使われる
2026/10/04(日) 03:43:53.07ID:aFzbMdMV
>>274
何も知らないなら何も言わないほうが良いぞ
馬鹿がバレるから
2026/10/04(日) 03:49:14.20ID:B8z1dF/a
AとB二つの別々の型のオブジェクトに共通のコードを書く時
両オブジェクトを受け付ける抽象型を使ってコードを書いてるね
2026/10/04(日) 03:54:18.00ID:kQKcSK1F
>>275
プログラミング言語は色んなのかあってピンキリだから各言語に適したやり方を許容するしかないんじゃない
2026/10/04(日) 04:01:09.47ID:b4mgkJGG
うちはABCで抽象型を作ります
レスを投稿する


ニューススポーツなんでも実況