web-dev-qa-db-ja.com

Swift関数と計算されたプロパティ

次のようなクラスEventがあるとします。

class Event {
    private var attendees: [Person] = []

    // Case 1
    //*******
    // Should I use a func…
    func countOfAttendees() -> Int {
        return attendees.count
    }

    // …or a var
    var countOfAttendees: Int {
        return attendees.count
    }

    // Case 2
    //*******
    // Should I use a func…
    func countOfPaidAttendees() -> Int {
        return attendees.filter({$0.hasPaid}).count
    }

    // …or a var
    var countOfPaidAttendees: Int {
        return attendees.filter({$0.hasPaid}).count
    }
}

上記の2つのケースでfunctionsまたはcomputed propertiesを使用するのがベストプラクティスですか?

28
Ashley Mills

niform Access Principle に従います。

モジュールによって提供されるすべてのサービスは、統一された表記法を介して利用可能である必要があります。これは、それらがストレージを介して実装されるか、計算を介して実装されるかを裏切るものではありません。

私にとって、これは、引数を取らず値を返す関数を記述しないことを意味します。私は常に計算されたプロパティを使用します。このようにして、後で計算されたプロパティを保存されたプロパティに変更することを決定した場合、アプリ内のすべての場所で括弧を削除することなく、保存されたプロパティの値のみを返す別の「getter」メソッドを使用することなく変更できます。プロパティ、かなり無駄な私見です。

また、格納されたプロパティを計算されたプロパティに変更する場合、その最後、およびアプリで使用されているすべての場所に括弧を追加する必要はありません。

16
Daniel T.

計算の複雑さと使用頻度の関係によると思います。

  • O(1)/_*_の場合、計算されたプロパティを使用します。
  • O(N)+/_rare-use_の場合は、関数を使用します。
  • それがO(N)+/_frequent-use_の場合、将来的にキャッシングまたは他の「スマート」手法を使用して複雑さを補正するかどうかを検討します。「はい」の場合、「いいえ」の場合、プロパティを使用します。 -いいえいいえ、それはただ重いです」そして関数を使用します。
18
courteouselk

私は最近Kotlinを学び始めました、そして彼らは計算されたプロパティをいつ使うべきかについて素晴らしいヒューリスティックを持っています:

関数とプロパティ

場合によっては、引数のない関数は読み取り専用プロパティと交換可能です。セマンティクスは似ていますが、どちらを優先するかについてはいくつかのスタイル上の規則があります。

基本となるアルゴリズムが次の場合、関数よりもプロパティを優先します。

  • 投げません
  • O(1)複雑さ
  • 計算するのが安い(または最初の実行時に計算される)
  • 呼び出しに対して同じ結果を返します

- https://kotlinlang.org/docs/reference/coding-conventions.html

10
Daniel T.

Swiftでは、パラメーターのない関数と計算されたプロパティはほぼ同じ機能を備えています(パラメーターのない関数もクロージャーであるのに対し、計算されたプロパティはそうでないという違いがあるかもしれません)。

意味的に違います。コードがアクションを実行し、そのアクションの結果の説明などを返す場合は、関数を使用します。コードがプロパティを計算するが、ユーザーの観点からは、これがストアドプロパティであるか、キャッシュされた値を最初に更新する必要があるストアドプロパティである可能性がある場合は、計算されたプロパティを使用します。

大きな違い:関数または計算されたプロパティを2回呼び出すとどうなりますか?計算されたプロパティの場合、x =プロパティであると予想します。 y =プロパティは、x =プロパティとまったく同じ動作をします。 y = x。ただし、実行速度が少し遅くなる場合があります。関数については、動作が異なっていても驚かないでしょう。

7
gnasher729

countOfAttendeesおよびcountOfPaidAttendees()を使用します。


計算された変数は、アクセスされるたびに計算された値を返す変数です。つまり、値は保存されません。内部的には関数として実装されています。

関数との違いは何ですか?

  • 意味的に、変数は状態であり、関数はアクションです。
  • 関数は、プライベートストレージへのアクセスを規制します。計算された変数は、よりコンパクトな方法で同じことを行うことができます。
  • 計算された変数はKVOで使用でき、#keypathとして渡され、監視する機能があります:willSet、didSet。

いつ変数を使用すべきですか

  • 投げない
  • 単純なプロパティを返します
  • 名前に副作用や動詞はありません
  • それはO(1)です。つまり、大きなコストは発生しません。あなたの例では、O(n)になります。
  • それはべき等です。複数の同一の呼び出しが同じ値を返すか、オブジェクトを同じ状態に設定します。

関数よりも変数を好む無関係な理由

  • 計算変数を使用すると、()を入力する必要がなくなります。ただし、簡潔さよりも明快さが重要であるため、これは弱い議論です。
  • 読み取り専用変数は、読み取り/書き込みとしてオーバーライドできます。関数は、常に読み取り専用であることを示します。ただし、Appleは、array.countなどの読み取り専用変数のプロパティを使用します。疑わしい場合は、プラットフォームとの一貫性を求めてください。

資源

From WWDC 2014-204 Cocoaの新機能 > 24:40 @propertyを使用する場合

オブジェクトの値または状態、または他のオブジェクトとの関係に関するあらゆるものにプロパティを使用します。悪い候補:

  • 物事を行うメソッド:ロード、解析、トグル、…。彼らはその名前に動詞を持っています。
  • ジェネレーター:init、copy、enumerated、…。これらのメソッドはべき等ではありません。
  • 状態を変更するメソッド:nextObject。

From Swift Style by Erica Sadun > Computed Properties vs. Methods

プロパティはインスタンスの固有の品質を表し、メソッドはアクションを実行します。

  • メソッドにはパラメーターがあります。プロパティはありません。副作用のある呼び出しにはメソッドを優先します。メソッドが何かを行う(たとえば、ロード、解析、トグル、出力など)か、動詞名を持っている場合は、プロパティであってはなりません。
  • 取得および/または設定できる単純な値のプロパティを優先します。
  • プロパティは、型インスタンスの意味的な本質的な品質を表現する必要があります。
  • プロパティを使用すると、willSetおよびdidSetを介してオブザーバーを追加できます。ストアドインスタンスプロパティとは異なり、ストアドタイププロパティには常にデフォルト値を指定する必要があります。

Kotlinコーディング規約から>関数vsプロパティ 。上記の Danielの回答 を参照してください。

関連情報のないその他のリソース:

5
Jano

funcを使用します。オブジェクト指向プログラミングは、計算されたプロパティがなくても問題なく機能します。計算またはフィルター処理された値が返されるため、計算されたプロパティが適切であると主張する人もいます。しかし、ここに私の不満があります。それを行うと、読みやすさは大きな影響を受けます。

このコンテキストでは、計算された値を割り当てようとしても意味がありません(そして、幸運にもIDEはこれを回避するのに役立ちます)。しかし、計算されたが、値?

event.countOfAttendees = 0; // not possible

Funcを使用している間、呼び出し元は値を直接処理していないことを知っています。

event.countOfAttendees()

私は、その動作オブジェクトであれば、データ構造のように見えるのではなく、動作するように見えるべきだと思います。オブジェクトがばかげて動作がない場合は、なぜそれをカプセル化しようとするのでしょうか。その場合は、出席者を公開することもできます。

3
morbidhawk