演算子のオーバーロードに対する引数を理解していません[非公開]


82

私は彼が言うジョエルの記事の一つを読んだ:

一般的に、私は物事を隠す言語機能が少し怖いことを認めなければなりません。コードが表示されたら

i = j * 5;

…Cでは、少なくとも、jに5が乗算され、結果がiに格納されていることがわかります。

しかし、C ++で同じコードスニペットを見ると、何もわかりません。なし。C ++で実際に何が起こっているのかを知る唯一の方法は、iとjの型を調べることです。これは、jがoperator*オーバーロードされた型であり、乗算しようとするとひどく機知に富んだ動作をするためです。

(エンファシス鉱山。)物事を隠す言語機能が怖い?どうしてそれが怖いの?物事を隠すこと(抽象化とも呼ばれます)は、オブジェクト指向プログラミングの重要なアイデアの1つではありませんか?methodを呼び出すたびにa.foo(b)、それが何をするのかまったくわかりません。あなたは他のどこかで宣言されるかもしれないタイプabは何かを見つけなければなりません。それでは、オブジェクト指向プログラミングはプログラマからあまりにも多くのことを隠してしまうので、オブジェクト指向プログラミングを廃止すべきでしょうか?

そして、演算子のオーバーロードをサポートしていない言語で記述する必要があるかもしれないとはどうj * 5違いj.multiply(5)ますか?繰り返しになりますが、loとbeholdは、非常に機知に富んだ何かを行うメソッドを持つ型である可能性があるためjmultiplyメソッドの型とピークをメソッド内で調べる必要があります。jmultiply

「ムアハハ、私はメソッドmultiplyに名前を付ける邪悪なプログラマーですが、実際にそれが行うことは完全に曖昧で直感的ではなく、物事を増やすこととはまったく関係ありません。」それはプログラミング言語を設計するときに考慮しなければならないシナリオですか?次に、誤解を招く可能性があるという理由で、プログラミング言語の識別子を放棄する必要があります!

メソッドが何をするのか知りたい場合は、ドキュメントを見るか、実装の内部を覗いてください。演算子のオーバーロードは単なる構文上のシュガーであり、それがゲームをどのように変えるかはわかりません。

教えてください


20
+1:よく書かれ、議論があり、興味深いトピックであり、議論の余地があります。p.se質問の輝かしい例。
アロングラネネク

19
+1:ジョエル・スポルスキーはよく書かれており、よく知られているため、人々は耳を傾けます。しかし、それは彼を常に100%正しいものにするわけではありません。あなたの主張に同意します。ここでJoelの論理に従えば、どこにも到達できません。
誰も

5
私は、iとjのいずれかがローカルに宣言されているため、それらの型をすばやく確認できるか、変数名がひどく、適切に名前を変更する必要があると主張します。
キャメロンマクファーランド

5
+1ですが、ジョエルの記事の最大の部分を忘れないでください。正しい答えに向かってマラソンを走った後、彼は明白な理由なしに50フィートで止まります。間違ったコードは単に間違って見えるべきではありません。コンパイルすべきではありません。
ラリーコールマン

3
@Larry:クラスを適切に定義することで、間違ったコードのコンパイルを失敗させることができます。そのため、彼の例では、C ++でSafeStringとUnsafeStringを使用できます。
デビッドソーンリー

回答:


32

抽象化はコードを「隠す」ため、内部の動作を気にする必要がなく、多くの場合、変更することはできませんが、意図はそれを見るのを妨げることではありません。私たちは演算子について仮定するだけで、Joelが言ったように、それはどこにでもある可能性があります。オーバーロードされたすべてのオペレーターを特定の場所に確立する必要があるプログラミング機能があると、それを見つけるのに役立つかもしれませんが、使いやすくなるかどうかわかりません。

データを削除するGet_Some_Dataと呼ばれる関数よりも*乗算によく似ていないことを*させることはありません。


13
+1「表示されない」ビットの場合。言語機能は使用目的であり、乱用ではありません。
マイケルK

5
しかし<<、C ++の標準ライブラリでは、ビット単位のシフトとは関係のないストリームに演算子が定義されています。
マルコム

「ビット単位シフト」演算子は、歴史的な理由からのみ呼び出されます。標準型に適用されると、ビット単位のシフトを行います(数値型に適用されるときに+演算子が数値を加算するのと同じ方法で)が、複雑な型に適用されると、好きなことを行うことができますそのタイプのセンス。
gbjbaanb

1
*は、(スマートポインターとイテレーターによって行われるように)逆参照にも使用されます。良いオーバーロードと悪いオーバーロードの境界をどこに置くかは明確ではありません
-martinkunev

それはどこにもありません。jの型定義にあります。
アンディ

19

私見では、演算子のオーバーロードなどの言語機能により、プログラマはより強力になります。そして、ご存じのとおり、大きな力には大きな責任が伴います。より多くのパワーを提供する機能は、あなた自身を足で撃つためのより多くの方法を提供し、そして明らかに、慎重に使用されるべきです。

例えば、それが過負荷に完璧な理にかなっている+*のための演算子class Matrixまたはをclass Complex。誰もが即座にその意味を理解します。一方、私にとっては+、Javaが言語の一部としてこれを行い、STLがstd::string演算子のオーバーロードを使用するにもかかわらず、文字列の連結を意味するという事実はまったく明らかではありません。

演算子のオーバーロードがコードをより明確にするもう1つの良い例は、C ++のスマートポインターです。スマートポインターをできる限り通常のポインターのように動作させたいので、単項演算子*->演算子をオーバーロードすることは完全に理にかなっています。

本質的に、演算子のオーバーロードは、関数に名前を付けるための単なる別の方法にすぎません。また、関数の命名規則があります。名前は説明的なものでなければならず、関数が何をするのかがすぐにわかるようにしなければなりません。同じ正確なルールが演算子のオーバーロードに適用されます。


1
最後の2つの文は、演算子のオーバーロードに対する異議の中心になります。つまり、すべてのコードがすぐに明らかになるという願望です。
ラリーコールマン

2
MとNがMatrix型である場合、M * Nの意味が明らかではないでしょうか?
ディマ

2
@フレッド:いいえ。行列乗算には1つの種類があります。mxn行列にnxk行列を乗算して、mxk行列を取得できます。
ディマ

1
@FredOverflow:3次元ベクトルを乗算するにはさまざまな方法があります。1つはスカラーを与え、もう1つは別の3次元ベクトルを与えるため*、それらのオーバーロードは混乱を引き起こす可能性があります。おそらくoperator*()、ドット積とoperator%()クロス積に使用できますが、汎用ライブラリには使用しません。
デビッドソーンリー

2
@Martin Beckett:いいえ。C++はどちらA-BとしてB-Aも並べ替えることはできません。すべての演算子はそのパターンに従います。常に1つの例外があります。コンパイラーが問題ではないことを証明できる場合、すべてを再配置することができます。
シェード

9

Haskellでは、「+」、「-」、「*」、「/」などは単なる(中置)関数です。

「4 plus 2」のように中置関数に「plus」という名前を付ける必要がありますか?加算はあなたの関数が何をするものなのか。「プラス」機能に「+」という名前を付ける必要がありますか?何故なの。

いわゆる「演算子」の問題は、それらがほとんど数学的な操作に似ており、それらを解釈する方法があまりないため、そのようなメソッド/関数/演算子が何をするかについて大きな期待があると思います。

編集:私のポイントをより明確にしました


Erm、Cから継承されたものを除いて、C ++(およびFredが尋ねたもの)はほとんど同じことを行います。さて、これが良いか悪いかについてあなたはどう思いますか?
sbi

@sbi私は実際にも、Cがオーバーロードしている事業者は...あなたがのためにそれらを使用することができます...演算子のオーバーロードを愛しintfloatlong longと何でも。それで、それは何についてですか?
-FUZxxl

@FUZxxl:これは、組み込みの演算子をオーバーロードするユーザー定義演算子に関するものです。
sbi

1
@sbi Haskellにはbuiltinuser-definedの区別はありません。すべての演算子は等しいです。事前定義されたものをすべて削除する拡張機能を有効にして、演算子を含む何でもゼロから作成することもできます。
FUZxxl

@FUZxxl:そうかもしれませんが、それらの対立するオーバーロードされた演算子は通常+、さまざまな組み込み数値型に組み込みを使用することに反対しませんが、ユーザー定義のオーバーロードを作成します。したがって、私のコメント。
sbi

7

私が見た他の答えに基づいて、演算子のオーバーロードに対する実際の反対は、すぐに明らかなコードに対する欲求であると結論付けることができます。

これは2つの理由で悲劇的です:

  1. 論理的な結論に達すると、コードはすぐに明らかになるという原則により、すべてCOBOLでコーディングすることになります。
  2. すぐにわかるコードから学ぶことはありません。あなたはそれがどのように機能するかを考えるのに時間をかけると理にかなっているコードから学びます。

ただし、コードからの学習が常に主要な目的とは限りません。「機能Xに不具合があり、それを書いた人が会社を辞め、すぐに修正する必要がある」などの場合、すぐに明らかになるコードが必要です。
Errorsatz

5

ある程度同意します。

あなたが書く場合はmultiply(j,5)j作る、スカラまたはマトリックスタイプのものであってもよいmultiply()ものに応じて、多かれ少なかれ複雑ですj。あなたは完全にオーバーロードするの考えを放棄する場合は、その関数は、指定しなければならないであろうmultiply_scalar()か、multiply_matrix()下に何が起こっていることが明らかになるだろうています。

私たちの多くが一方的にそれを好むコードがあり、私たちのほとんどが他の方法でそれを好むコードがあります。ただし、ほとんどのコードは、これらの両極端の中間に位置します。あなたがそこで何を好むかは、あなたの背景と個人的な好みに依存します。


いい視点ね。しかし、完全に過負荷を放棄することは、一般的なプログラミング...で素晴らしいプレーしない
fredoverflow

@FredO:もちろん違います。しかし、ジェネリックプログラミングは、非常に異なる型に対して同じアルゴリズムを使用することに関するものmultiply_matrix()なので、好む人はジェネリックプログラミングも好きではありません。
sbi

2
あなたは名前についてかなり楽観的ですか?私が働いたいくつかの場所に基づいて、「multiply()」や「multiplym()」などの名前を期待していますreal_multiply()。開発者は多くの場合、名前が苦手でoperator*()、少なくとも一貫性が保たれます。
デビッドソーンリー

@デビッド:ええ、名前が悪いかもしれないという事実をスキップしました。しかし、その後、私たちは、operator*()愚かな何かをするかもしれないと仮定するかもしれません、j5つの関数呼び出しを含む式に評価するマクロであり、その他はそうではありません。その後、2つのアプローチを比較することはできなくなります。しかし、はい、物事にうまく名前を付けるのは難しいですが、時間はかかりますが。
sbi

5
@David:物事に名前を付けるのは難しいので、名前はプログラミング言語から追放すべきですよね?それらを間違えるのは簡単すぎます!;-)
fredoverflow

4

演算子のオーバーロードには2つの問題があります。

  1. オーバーロードは、プログラマーが意図していない場合でも、演算子のセマンティクスを変更します。たとえば、、またはをオーバーロードすると&&、これらの演算子の組み込みバリアントによって暗示されるシーケンスポイント(および論理演算子の短絡動作)が失われます。このため、言語で許可されていても、これらの演算子をオーバーロードしない方が良いでしょう。||,
  2. 一部の人々は、演算子のオーバーロードをこのような素晴らしい機能と見なし、適切なソリューションではない場合でも、どこでも使用し始めます。これにより、他の人が他の方向に過剰に反応し、オペレータのオーバーロードの使用に対して警告します。私はどちらのグループにも同意しませんが、中間的な立場を取ります:演算子のオーバーロードは控えめに、そして
    • 過負荷のオペレーターは、ドメインの専門家とソフトウェアの専門家の両方にとって自然な意味を持ちます。これらの2つのグループが演算子の自然な意味に同意しない場合、それをオーバーロードしないでください。
    • 関係する型については、演算子に自然な意味はなく、直接のコンテキスト(同じ式が望ましいが、数行以内)が常に演算子の意味を明確にします。このカテゴリの例はoperator<<、ストリーム用です。

1
私からの+1ですが、2番目の引数は継承にも同様に適用できます。多くの人々は、継承についての手がかりを持たず、それをすべてに適用しようとします。ほとんどのプログラマーは、継承を誤用する可能性があることに同意すると思います。それは、継承が「悪」であり、プログラミング言語から放棄されるべきだということですか?それとも、役に立つ可能性があるため、そのままにしておくべきでしょうか?
fredoverflow

@FredOverflow 2番目の引数は、「新しくてホットな」ものに適用できます。私は、言語から演算子のオーバーロードを取り除くための引数としてではなく、人々がそれに対して反論する理由として与えています。私に関する限り、演算子のオーバーロードは有用ですが、注意して使用する必要があります。
バートヴァンインゲンシェナウ

私見では、のオーバーロードが可能&&||C ++は、これらの過負荷できるようにするつもりだった場合はシーケンシングを意味するものではありません方法では、大きな間違い(私見、だった、それが必要とされている最初の関数で、特別な「二機能」の形式を使用している必要があります暗黙的に整数に変換可能な型を返すには、2番目の関数が2つまたは3つの引数を取り、2番目の関数の「余分な」引数が最初の関数の戻り型になります。コンパイラは最初の関数を呼び出し、ゼロ以外を返した場合、2番目のオペランドを評価し、2番目の関数を呼び出します。)
supercat

もちろん、それはカンマ演算子のオーバーロードを許可するほど奇妙ではありません。ちなみに、私が実際に見たことがありませんが、したいオーバーロードのようなものは、メンバーアクセスを密結合する手段であり、式をメンバーの公開を要求するのではなく、クラスfoo.bar[3].Xによって処理することを可能にします添え字をサポートしてからメンバーを公開できます。実際のメンバーアクセスを介して評価を強制する場合は、と記述します。foofooX((foo.bar)[3]).X
-supercat

3

私の個人的な経験に基づいて、複数のメソッドを許可するが、演算子をオーバーロードしないJavaの方法は、演算子を見たときはいつでもそれが何をするかを正確に知っていることを意味します。

*奇妙なコードを呼び出すかどうかを確認する必要はありませんが、それが乗算であることを知っており、Java言語仕様で定義されている方法とまったく同じように動作します。これは、プログラマーによって定義されたすべてのウィケットを見つけるのではなく、実際の動作に集中できることを意味します。

言い換えると、オペレーターのオーバーロードを禁止することは、ライターではなくリーダーにとっての利点であり、したがってプログラムの保守が容易になります!


+1、注意:C ++を使用すると、首を吊るのに十分なロープが提供されます。しかし、C ++でリンクリストを実装する場合は、[]を使用してn番目の要素にアクセスする機能が必要です。(数学的に言えば)有効なデータに演算子を使用するのは理にかなっています。
マイケルK

@マイケル、あなたはlist.get(n)構文で生きることはできませんか?

@Thorbjørn:それも実際には問題ありません。おそらく悪い例です。time.add(anotherTime)よりも、+、-をオーバーロードすると意味があります。
マイケルK

4
@Michael:リンクされたリストについて、std::listオーバーロードしませんoperator[](または、リストにインデックスを付ける他の手段を与えません)。そのような操作はO(n)であり、効率を重視する場合、リストインターフェイスはそのような関数を公開しないためです。クライアントは、インデックス付きのリンクリストを反復処理して、O(n)アルゴリズムを不必要にO(n ^ 2)にしたいと思うかもしれません。Javaコードでは、特にList複雑さを完全に抽象化することを目的とするインターフェイスを使用している場合は特にそうです。
fredoverflow

5
@Thor:「しかし、確認する必要があるため:)」...繰り返しますが、これは演算子のオーバーロードとは関係ありません。が表示time.add(anotherTime)された場合は、ライブラリプログラマーが追加操作を「正しく」実装したかどうかも確認する必要があります(それが何であれ)。
fredoverflow

3

オーバーロードa * bと呼び出しの違いの1つmultiply(a,b)は、後者を簡単にgrepできることです。multiply関数がさまざまな型に対してオーバーロードされていない場合、aおよびの型を追跡することなく、関数が何をするかを正確に知ることができますb

Linus Torvaldsには、演算子のオーバーロードに関する興味深い議論があります。ほとんどの変更がパッチを介して電子メールで送信されるLinuxカーネル開発のようなものでは、メンテナーが各変更の前後数行のコンテキストでパッチが何をするかを理解できることが重要です。関数と演算子がオーバーロードされていない場合、すべてのタイプが何であるかを調べ、オーバーロードされた演算子をチェックする必要がないため、パッチはコンテキストに依存しない方法でより簡単に読み取ることができます。


Linuxカーネルは純粋なCで開発されていませんか?なぜこのコンテキストで(演算子)のオーバーロードを議論するのですか?
fredoverflow

言語に関係なく、同様の開発プロセスを持つプロジェクトでも懸念事項は同じです。過剰なオーバーロードは、パッチファイルの数行だけを続けなければならない場合、変更の影響を理解するのを難しくする可能性があります。
スコットウェールズ

@FredOverflow:Linuxカーネルは本当にGCC Cにあります。あらゆる種類の拡張機能を使用して、CにC ++の感覚を与えます。私はいくつかの派手なタイプの操作を考えています。
ザンリンクス

2
@Scott:Cには関数をオーバーロードする能力がないため、Cでプログラムされたプロジェクトに関してオーバーロードの「悪さ」について議論する意味はありません。
fredoverflow

3
リーナス・トーバルズは狭い視野を持っているように思えます。彼は、Linuxカーネルのプログラミングにはあまり役に立たないものを、一般的な使用には適さないように批判することがあります。Subversionはその一例です。素晴らしいVCSですが、Linuxカーネルの開発には分散VCSが本当に必要なので、LinusはSVNを一般的に批判しました。
デビッドソーンリー

2

期待を破ることと関係があるのではないかと思います。私はあなたがC ++に慣れていて、言語によって完全に指示されない演算子の振る舞いに慣れており、演算子が奇妙なことをしても驚かないでしょう。その機能を持たない言語に慣れていて、C ++コードを見ると、それらの他の言語からの期待が持ち込まれ、オーバーロードされた演算子がファンキーなことをしていることに気がつくと驚くかもしれません。

個人的には違いがあると思います。言語のビルトイン構文の動作を変更できる場合、それを推論するのはより不透明になります。メタプログラミングを許可しない言語は、構文的には強力ではありませんが、概念的には理解しやすいです。


オーバーロードされたオペレーターは、決して「奇妙なこと」をしないでください。もちろん、何か複雑なことをしても大丈夫です。ただし、明らかな意味を持つ場合にのみオーバーロードします。
シェード

2

数学演算子のオーバーロードは、C ++の演算子オーバーロードの本当の問題ではないと思います。式(つまり型)のコンテキストに依存するべきではない演算子のオーバーロードは「悪」だと思います。例えば、オーバーロード, [ ] ( ) -> ->* new deleteまたは単項*。これらのオペレーターには、決して変更してはならない一定の期待があります。


+1 []を++と同等にしないでください。
マイケルK

3
あなたが言及た演算子をオーバーロードすることはできないと言っているのですか?それとも、私たちは健全な目的のためだけにそれらをオーバーロードすべきだと言っているのですか?なぜならoperator[]、コンテナなし、ファンクタなしoperator()、スマートポインタなしoperator->などを見たくないからです。
fredoverflow

演算子を数学演算でオーバーロードする潜在的な問題は、それらの演算子に比べて小さいと言っています。数学演算子で賢いことやクレイジーなことをするのは面倒かもしれませんが、私がリストした演算子は、通常は演算子ではなく基本的な言語要素とは考えられず、言語で定義された期待を常に満たす必要あります。[]常に配列のようなアクセサーである->必要があり、常にメンバーへのアクセスを意味する必要があります。実際に配列であるか別のコンテナであるか、スマートポインタであるかどうかは関係ありません。
アロングラネレク

2

隠蔽についてのジョエルの議論が好きではないことを完全に理解しています。私でもない。実際、組み込みの数値型のようなものや、たとえばマトリックスのような独自の型には、「+」を使用する方がはるかに優れています。「.multiply()」の代わりに「*」を使用して2つの行列を乗算できることは、これがきちんとしてエレガントであることを認めます。そして、結局のところ、両方のケースで同じ種類の抽象化を持っています。

ここで痛いのは、コードの可読性です。実際のケースでは、マトリックス乗算の学術的な例ではありません。特に、言語で最初に言語コアに存在しない演算子を定義できる場合など=:=。この時点で多くの余分な質問が発生します。そのいまいましいオペレーターとは何ですか?そのことの優先順位は何ですか?結合性とは何ですか?a =:= b =:= c実際に実行される順序は?

これはすでに演算子のオーバーロードに対する議論です。まだ納得できませんか?優先ルールを確認すると、10秒しかかかりませんでしたか?さて、さらに進んでみましょう。

演算子のオーバーロードを許可する言語、たとえば名前が「S」で始まる人気のある言語を使用し始めると、ライブラリ設計者が演算子をオーバーライドすることを好むことがすぐにわかります。もちろん、彼らは十分な教育を受けており、ベストプラクティスに従っています(ここでは皮肉屋ではありません)。それらを個別に見ると、すべてのAPIが完全に理にかなっています。

ここで、1つのコードで一緒にオーバーロードする演算子を多用するいくつかのAPIを使用する必要があると想像してください。またはさらに良い-あなたはそのようないくつかのレガシーコードを読む必要があります。これは、オペレーターのオーバーロードが本当にひどいときです。基本的に、1つの場所に多数のオーバーロード演算子がある場合、プログラムコード内の他の非英数字文字とすぐに混ざり始めます。実際には演算子ではなく、ブロックやスコープのようなものを定義したり、フロー制御ステートメントを整形したり、メタの事柄を示したりする、より基本的な言語の文法要素である英数字以外の文字と交わります。視覚的な混乱を理解するには、メガネを掛けて目をLCDディスプレイに10 cm近づける必要があります。


1
既存のオペレーターのオーバーロードと新しいオペレーターの発明は同じことではなく、私からの+1です。
fredoverflow

1

一般的に、直感的でない方法で演算子のオーバーロードを使用することは避けます。つまり、数値クラスがある場合、*のオーバーロードは受け入れられます(推奨されます)。ただし、クラスEmployeeがある場合、オーバーロード*はどうなりますか?言い換えれば、直観的な方法で演算子をオーバーロードし、読みやすく、理解しやすくします。

許容/推奨:

class Complex
{
public:
    double r;
    double i;

    Complex operator*(const Compex& rhs)
    {
        Complex result;
        result.r = (r * rhs.r) - (i * rhs.i);
        result.i = (r * rhs.i) + (i * rhs.r);
        return result;
    }
};

受け付けできません:

class Employee
{
public:
    std::string name;
    std::string address;
    std::string phone_number;

    Employee operator* (const Employee& e)
    {
        // what the hell do I do here??
    }
};

1
従業員を増やす?彼らが会議室のテーブルでそれを行う場合、それは確かに略奪行為です。
gbjbaanb

1

ここですでに述べたことに加えて、演算子のオーバーロードに対するもう1つの議論があります。実際、を書くと+、何かに何かを追加することを意味していることは明らかです。しかし、これは常にそうではありません。

C ++自体は、このような場合の優れた例です。どうやってstream << 1読むの?ストリームを左に1つシフトしましたか?C ++の<<もストリームに書き込むことを明示的に知っていない限り、まったく明らかではありません。ただし、この操作がメソッドとして実装されている場合、正気な開発者が書くo.leftShift(1)ことはありませんo.write(1)

肝心なのは、演算子のオーバーロードを利用できないようにすることで、言語がプログラマーに操作の名前を考えさせることです。選択した名前が完全ではない場合でも、記号よりも名前を誤って解釈することは困難です。


1

表記の方法と比較すると、演算子は短くなりますが、括弧も必要ありません。括弧は入力するのが比較的不便です。そして、それらのバランスを取る必要があります。合計すると、メソッド呼び出しには演算子と比較して3文字のプレーンノイズが必要です。これにより、演算子の使用が非常に魅力的になります。
なぜ他の人がこれを望んでいるのですcout << "Hello world"か?

オーバーロードの問題は、ほとんどのプログラマーが信じられないほど怠け者であり、ほとんどのプログラマーが余裕がないことです。

C ++プログラマーを演算子のオーバーロードの悪用に駆り立てているのは、その存在ではなく、メソッド呼び出しを実行するためのよりきちんとした方法がないことです。そして、人々はオペレーターのオーバーロードを恐れているだけでなく、それが可能だからです。
たとえば、RubyとScalaでは、演算子のオーバーロードを恐れる人はいないことに注意してください。事実とは別に、演算子の使用は実際にはメソッドよりも短くないという別の理由は、Rubyでは演算子のオーバーロードを合理的な最小値に制限しているのに対し、Scala では独自の演算子を宣言できるため、衝突を簡単に回避できます


または、C#で、+ =を使用してイベントをデリゲートに関連付ける場合。プログラマーの愚かさのために言語機能を非難することは建設的な前進だとは思いません。
gbjbaanb

0

演算子のオーバーロードが怖いのは、*単純に「乗算」を意味しないとは思わない多数のプログラマーがfoo.multiply(bar)いるからです。 。その時点で、彼らはなぜ疑問に思って調査に行きます。

私は、2つの引数を取り、一方から他方に値を適用してブール値を返す「CompareValues」と呼ばれるメソッドを作成する高レベルのポジションにいる「優秀なプログラマー」と協力しました。または、他の3つのオブジェクトのデータベースにアクセスし、値を取得し、計算を実行し、変更thisしてデータベースに保存する「LoadTheValues」というメソッド。

これらのタイプのプログラマーとチームで作業している場合、彼らが取り組んだことをすぐに調査することができます。彼らがオペレータを過負荷にした場合、彼らがやったと思って見に行くことを除いて、彼らがそれをやったことを知る方法はまったくありません。

完璧な世界、または完璧なプログラマーのいるチームでは、オペレーターのオーバーロードはおそらく素晴らしいツールです。私はまだ完璧なプログラマーのチームで仕事をしていないので、それが怖い理由です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.