プロパティの「ドット」表記ができました。ドット表記とメッセージ表記のメリットについて、さまざまな back および forths を見てきました。回答を汚さないようにするため、質問ではどちらの方法でも回答しません。
プロパティにアクセスするためのドット表記とメッセージ表記についてどう思いますか?
Objective-Cに重点を置いてください。Objective-CはObjective-Cであるという私の1つのバイアスは、JavaまたはJavaScriptは有効です。
有効な解説は、技術的な問題(操作の順序、キャストの優先順位、パフォーマンスなど)、明快さ(構造とオブジェクトの性質、賛成と反対の両方)、簡潔さなどに関するものです。
注:私は、コードの規則と品質が最重要である巨大なプロジェクト(書き込みが1000倍のパラダイムを一度読み取る)に取り組んだ、コードの厳密な品質と可読性の学派です。
動作にドットを使用しないでください。ドットを使用して、通常はプロパティとして宣言されている属性などの属性にアクセスまたは設定します。
x = foo.name; // good
foo.age = 42; // good
y = x.retain; // bad
k.release; // compiler should warn, but some don't. Oops.
v.lockFocusIfCanDraw; /// ooh... no. bad bad bad
Objective-Cを初めて使う人には、@ propertyとして宣言されたもの以外にはドットを使用しないことをお勧めします。言語を感じたら、正しいと思うことを行います。
たとえば、私は次のように完全に自然だと思います。
k = anArray.count;
for (NSView *v in myView.subviews) { ... };
Clangスタティックアナライザーは、ドットが特定のパターンにのみ使用されているか、他の特定のパターンには使用されていないことを確認できるようになると期待できます。
まず、Visual/Real Basicでプログラミングを始めてからJavaに移ったので、構文のドット表記にはかなり慣れていると言ってみましょう。しかし、ようやくObjective-Cに移動して角かっこに慣れ、Objective-C 2.0とそのドット構文の紹介を見たとき、本当に気に入らないことに気付きました。 (他の言語の場合、それは彼らが転がる方法だからです)。
私はObjective-Cにドット構文を持つ3つの主な牛肉を持っています。
ビーフ#1:これにより、エラーが発生する理由が明確になりません。たとえば、次の行があるとします。
something.frame.Origin.x = 42;
次に、something
がオブジェクトであり、オブジェクトの構造体を式の左辺値として使用できないため、コンパイラエラーが発生します。ただし、私が持っている場合:
something.frame.Origin.x = 42;
something
はNSRectメンバーを持つ構造体自体であり、私はcanをlvalueとして使用するため、これは問題なくコンパイルされます。
このコードを採用した場合、something
が何であるかを理解するために少し時間を費やす必要があります。それは構造体ですか?オブジェクトですか?ただし、ブラケット構文を使用すると、より明確になります。
[something setFrame:newFrame];
この場合、something
がオブジェクトであるかどうかにかかわらず、あいまいさはまったくありません。あいまいさの導入は私の牛肉#1です。
Beef#2:Cでは、ドット構文を使用して、メソッドを呼び出すのではなく、構造体のメンバーにアクセスします。プログラマーは、オブジェクトのsetFoo:
およびfoo
メソッドをオーバーライドしながら、something.foo
を介してそれらにアクセスできます。私の頭の中で、ドット構文を使用した式を見るとき、それらはivarへの単純な割り当てであると期待しています。 これは常に当てはまるわけではありません。配列とテーブルビューを仲介するコントローラーオブジェクトを考えてみましょう。 myController.contentArray = newArray;
を呼び出すと、古い配列が新しい配列に置き換えられると思います。ただし、元のプログラマーがsetContentArray:
をオーバーライドして、配列を設定するだけでなく、テーブルビューを再ロードした可能性もあります。行から、その動作の兆候はありません。私が[myController setContentArray:newArray];
を見たとしたら、「ああ、メソッドです。このメソッドの定義を確認して、何が行われているのかを確認する必要がある」と思います。
したがって、ビーフ#2の私の要約は、カスタムコードでドット構文の意味をオーバーライドできるということです。
ビーフ#3:見た目が悪いと思います。 Objective-Cプログラマーとして、私は完全に構文をブラケットで扱うことに慣れているので、行を読み、美しいブラケットの行を見て、次にfoo.name = newName; foo.size = newSize;
などで突然壊れるのは少し気が散ります。ドット構文(C構造体)が必要なものがあることに気づきましたが、それを使うのはそれだけです。
もちろん、自分でコードを作成している場合は、使いやすいものを使用してください。しかし、オープンソーシングを計画しているコードを書いている場合、または永久に維持することを期待しないコードを書いている場合は、ブラケット構文の使用を強くお勧めします。もちろん、これは私の意見です。
ドット構文に対する最近のブログ投稿: http://weblog.bignerdranch.com/?p=8
上記の投稿への反論: http://eschatologist.net/blog/?p=226 (ドット構文を支持する元の記事: http://eschatologist.net/blog/ ?p = 16 )
私は新しいCocoa/Objective-C開発者であり、私の見解は次のとおりです。
Obj-C 2.0から始めたにもかかわらず、ドット表記の方が慣れ親しんでいるにもかかわらず、私はメッセージング表記に固執します(Javaが私の第一言語です)。これの私の理由は非常に単純です:まだ正確に理解していません言語にドット表記を追加した理由。私には、不必要な「純粋でない」追加のように思えます。それが言語にどのように役立つかを誰かが説明できれば、私はそれを聞いて幸せです。
しかし、私はこれをスタイルの選択と見なし、正しいまたは間違った方法があるとは思いませんそれが一貫していて読みやすい限り、他のスタイルの選択と同じように(開口部を置くなど)メソッドヘッダーまたは次の行と同じ行に中括弧。
Objective-Cのドット表記は、通常のメッセージパッシングに変換される構文上のシュガーであるため、内部では何も変化せず、実行時に違いはありません。 ドット表記は、メッセージの受け渡しよりも絶対に高速ではありません。
これに少し前文が必要になった後、私が見た長所と短所はここにあります:
長所
@property
とドット表記を使用すると、コンパイラが多くの作業を行います。プロパティを取得および設定するときに、適切なメモリ管理のためのコードを生成できます。これが、ドット表記がApple自体の公式ガイドによって提案されている理由です。cons
@property
へのアクセスに対してのみ許可されます(1)複合演算子の使用法のコード例:
//Use of compound operator on a property of an object
anObject.var += 1;
//This is not possible with standard message notation
[anObject setVar:[anObject var] + 1];
言語自体と一致する言語のスタイルを使用することが、ここでの最良のアドバイスです。ただし、これはOOシステム(またはその逆))で機能コードを記述する場合ではなく、ドット表記はObjective-C 2.0の構文の一部です。
どのシステムも悪用される可能性があります。すべてのCベースの言語でのプリプロセッサの存在は、非常に奇妙なことを行うのに十分です。どれだけおかしいかを正確に知る必要がある場合は、 難読化されたCコンテスト を参照してください。それは、プリプロセッサが自動的に不良であり、決して使用すべきでないことを意味しますか?
インターフェースでそのように定義されているプロパティにアクセスするためのドット構文の使用は、悪用される可能性があります。ポテンシアでの虐待の存在は、必ずしもそれに対する反対ではありません。
プロパティアクセスには副作用がある場合があります。これは、そのプロパティを取得するために使用される構文に直交しています。 CoreData、委任、動的プロパティ(first + last = full)はすべて、必然的にいくつかの作業を実行します。しかし、それはオブジェクトの「プロパティ」と「インスタンス変数」を混同するでしょう。特に計算できる場合(たとえば、文字列の長さなど)、プロパティを必ずしもそのまま保存する必要がある理由はありません。したがって、foo.fullNameと[foo fullName]のどちらを使用する場合でも、動的な評価が行われます。
最後に、プロパティの動作(lvalueとして使用される場合)は、コピーが取得されるか、保持されるかなど、オブジェクト自体によって定義されます。これにより、メソッドを再実装しなくても、後でプロパティ定義自体で動作を簡単に変更できます。これにより、アプローチの柔軟性が高まり、結果として(実装)エラーが発生しにくくなります。間違った方法(つまり、保持ではなくコピー)を選択する可能性はまだありますが、それは実装上の問題ではなく、構造上の問題です。
結局のところ、それは「構造体のように見えるか」という質問に要約されます。これはおそらく、これまでの議論の主な差別化要因です。構造体がある場合、オブジェクトがある場合とは動作が異なります。しかし、それは常に真実でした。構造体にメッセージを送信することはできず、それがスタックベースか、リファレンス/ mallocベースかを知る必要があります。使用法([[CGRect alloc] init]またはstruct CGRect?)が異なるメンタルモデルはすでに存在します。彼らは行動の点で統一されたことはありません。それぞれのケースで何を扱っているかを知る必要があります。オブジェクトのプロパティ表記を追加しても、データ型を知っているプログラマーを混乱させることはほとんどありません。そうでない場合は、さらに大きな問題が発生します。
一貫性については; (Objective-)Cはそれ自体で矛盾しています。 =は、ソースコードの字句位置に基づいて、代入と等価の両方に使用されます。 *ポインタと乗算に使用されます。 BOOLは、YESおよびNOがそれぞれ1および0であるにもかかわらず、バイト(または他の整数値)ではなく文字です。一貫性や純粋さは、言語が設計されたものではありません。それは物事を成し遂げることでした。
したがって、使用したくない場合は使用しないでください。別の方法で実行してください。もしそれを使いたくて理解できれば、それを使っても大丈夫です。他の言語は、一般的なデータ構造(マップ/構造体)とオブジェクトタイプ(プロパティ付き)の概念を扱います。一方は単なるデータ構造であり、もう一方はリッチオブジェクトであるにもかかわらず、両方に同じ構文を使用することがよくあります。 Objective-Cのプログラマーは、好みのプログラミング方法でなくても、すべてのスタイルのプログラミングを処理できる同等の機能を備えている必要があります。
プロパティに使用するのは、
for ( Person *person in group.people){ ... }
よりも少し読みやすいです
for ( Person *person in [group people]){ ... }
2番目のケースでは、頭脳をメッセージ送信モードにすることで可読性が妨げられますが、1番目のケースでは、グループオブジェクトのpeopleプロパティにアクセスしていることは明らかです。
たとえば、コレクションを変更するときにも使用します。
[group.people addObject:another_person];
より少し読みやすいです
[[group people] addObject:another_person];
この場合の重点は、2つのメッセージをチェーンするのではなく、オブジェクトを配列に追加することです。
私は主にObjective-C 2.0の年齢で育ったので、ドット表記を好みます。私にとっては、コードを簡略化できるので、余分なブラケットを使用する代わりに、ドットのみを使用できます。
メッセージを送信するだけでなく、オブジェクトのプロパティにアクセスしているようにfeelになるので、ドット構文も好きです(もちろん、ドット構文は実際にメッセージ送信に変換されます) 、しかし見た目のために、ドットは違った感じになります)。古い構文で「ゲッターを呼び出す」代わりに、オブジェクトから何か有用なものを直接取得しているように感じます。
これに関する議論のいくつかは、「しかし、すでにドット構文があり、それはstructs
!のためのものです」に関係しています。そして、それは本当です。しかし、(そして、これは単に心理的なものです)基本的には同じように感じます。 dot-syntax feelsを使用してオブジェクトのプロパティにアクセスすることは、構造体のメンバーにアクセスすることと同じであり、多かれ少なかれ意図した効果です(私の意見では)。
****編集:bbumが指摘したように、オブジェクトの任意のメソッドを呼び出すためにドット構文を使用することもできます(私はこれを知りませんでした)。したがって、ドット構文に関する私の意見は、オブジェクトのプロパティを処理するためだけのものであり、毎日のメッセージ送信ではありません**
私はメッセージングの構文を非常に好みます...しかし、それが私が学んだことだからです。私のクラスの多くとObjective-C 1.0スタイルにないものを考えると、それらを混在させたくありません。ドット構文を使用しないのは、「慣れている」以外に本当の理由はありません...これを除いて、これは私を狂気にさせます
[myInstance.methodThatReturnsAnObject sendAMessageToIt]
理由はわかりませんが、理由はまったくありません。私はそうしていると思います
[[myInstance methodThatReturnsAnObject] sendAMessageToIt]
より読みやすいです。しかし、一人一人に!
オブジェクト指向プログラミングの主な利点の1つは、オブジェクトの内部状態に直接アクセスできないことです。
ドット構文は、まるで状態が直接アクセスされているかのようにルックアンドフィールを作成しようとする試みのようです。しかし、実際には、それは動作-fooおよび-setFoo:に対する単なる構文上の砂糖です。私自身、スペードをスペードと呼びます。ドット構文は、コードがより簡潔であるほど読みやすさを向上させますが、実際に-fooおよび-setFoo:を呼び出していることを覚えておかないと、問題を引き起こす可能性があるため、理解に役立ちません。
合成アクセサは、状態が直接アクセスされるオブジェクトを簡単に記述できるようにする試みのようです。私の考えでは、これにより、オブジェクト指向プログラミングが回避するために作成された種類のプログラム設計がまさに促進されます。
結局のところ、ドット構文とプロパティは導入されたことはありません。私は、ObjCがSmalltalkのようにするためのCのいくつかのクリーンな拡張であることを人々に伝えることができましたが、それはもう本当ではないと思います。
正直なところ、スタイルの問題だと思います。私は個人的にはドット構文に反対しています(特に、変数の読み取り/書き込みだけでなく、メソッド呼び出しに使用できることを知った直後)。ただし、それを使用する場合は、変数へのアクセスと変更以外の目的でnotを使用することを強くお勧めします。
多くの人が「プロパティ」と「インスタンス変数」を混同しているようです。プロパティのポイントは、内部を知らなくてもオブジェクトを変更できるようになることだと思います。インスタンス変数は、ほとんどの場合、プロパティの「実装」(つまり「インターフェイス」)ですが、常にそうであるとは限りません。プロパティがivarに対応していない場合があり、代わりに戻り値を計算します '急いで'。
そのため、「ドット構文は、変数にアクセスしていると思い込ませて混乱させる」という考えが間違っていると信じています。ドットやブラケットは、内部についての仮定を行うべきではありません。それはプロパティであり、ivarではありません。
私の意見では、ドット構文はObjective-CをSmalltalk風に抑えます。コードをよりシンプルに見せることができますが、あいまいさを追加します。 struct
、union
、またはオブジェクトですか?
ドット表記を使用(できる限り)
いくつかの値を返すインスタンスメソッド
ドット表記を使用しない
Voidを返すインスタンスメソッド、initメソッド、またはClassメソッド。
そして私の個人的なお気に入りの例外
NSMutableArray * array = @[].mutableCopy;
怠惰と呼んでください。でも、「。」を1つ入力する必要がある場合。同じ結果を得るには毎回2つ[]を使用します。冗長な言語は嫌いです。 LISPの()は私を混乱させました。数学などのエレガントな言語は簡潔で効果的ですが、他の言語はすべて不十分です。
ドット表記は、メッセージを構造体のメンバーへのアクセスのように見せようとしますが、そうではありません。場合によっては正常に動作する可能性があります。しかし、すぐに誰かがこのようなものを思いつくでしょう:
NSView *myView = ...;
myView.frame.size.width = newWidth;
元気そう。しかし、そうではありません。それは同じです
[myView frame].size.width = newWidth;
これは機能しません。コンパイラーは最初のものを受け入れますが、当然2番目のものは受け入れません。そして、それが最初にエラーまたは警告を発したとしても、これは混乱を招くだけです。
頭の中でobject.instanceVarはinstanceVarに属しているため、ドット表記の代わりにメッセージングに切り替える可能性があると思いますobject、私にとってはmethod callのようには見えないので、アクセサで起こっていることがあり、 instanceVarまたはself.instanceVarを使用すると、単純な暗黙的なものと明示的なものよりもはるかに大きな違いが生じる可能性があります。ちょうど私の2¢。
私は個人的にコードでドット表記をまったく使用しません。必要な場合にのみ、CoreData KVCバインディング式で使用します。
私がコードでそれらを使用しない理由は、ドット表記がセッターのセマンティクスを隠すためです。ドット表記でプロパティを設定すると、セッターのセマンティクス(割り当て/保持/コピー)に関係なく、常に割り当てのように見えます。メッセージ表記を使用すると、受信側オブジェクトがセッターで発生することを制御でき、それらの影響を考慮する必要があるという事実を強調できます。
KVC準拠のプロパティまたは宣言されたプロパティの値を取得するときにドット表記を使用するかどうかはまだ検討中です。これは、明らかにコンパクトで読みやすく、隠されたセマンティクスがないためです。現在、一貫性を保つためにメッセージ表記を使用しています。
確かに、Objective-Cのドット表記は奇妙に見えます。しかし、それなしではまだ次のことはできません。
int width = self.frame.size.width;
正常に動作しますが、:
int height = [[[self frame] size] height];
「ポインタ型に変換できません」と表示されます。ただし、コードの表示をメッセージ表記と一致させたいと思っています。