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


26

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つのケースで関数または計算されたプロパティを使用するのがベストプラクティスですか?


2
stackoverflow.com/questions/24035276/… ...要するに、「関数を関数にし、プロパティをプロパティにします。」
ロバートハーヴェイ

回答:


14

統一アクセス原則に従ってください、

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

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

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


私はもともと@Antonの複雑さの答えを使用しましたが、実際には、これが私がそれを行う方法であることに気づきました...デフォルトではプロパティです。
アシュリーミルズ

17

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

  • O(1)/の場合*、計算されたプロパティを使用します。
  • O(N)+/の場合rare-use、関数を使用します。
  • O(N)+/の場合frequent-use、将来的にキャッシングまたは他の「スマート」テクニックを使用して複雑さを補うかどうかを検討します。 。

2
面白いのは、私が同じ推論を使用してそれを始めた方法です。オブジェクトを変更しない限り、軽量処理を行う必要がある場合でも、プロパティであるという印象を与えることができる場合は、プロパティにします。
ディールソン販売

9

私は最近Kotlinの学習を開始しましたが、計算されたプロパティをいつ使用するかについて非常にヒューリスティックです。

関数とプロパティ

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

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

  • 投げない
  • O(1)の複雑さ
  • 計算が安価です(または最初の実行時にcaсhed)
  • 呼び出しに対して同じ結果を返します

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


プロパティは(まだ?)スローできないため、「スローしない」もSwiftにとって重要です
alejandromp

「O(1)の複雑さ」がドキュメントから削除されました
Mahmoud Shahoud

7

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

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

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


4

とを使用countOfAttendeescountOfPaidAttendees()ます。


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

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

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

次の場合に変数を使用する必要があります

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

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

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

資源

WWDC 2014 - 204ココアの新機能  > 24:40 @propertyを使用するとき

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

  • ロード、解析、トグルなどを行うメソッド。名前に動詞があります。
  • ジェネレーター:init、copy、enumerated、…。これらのメソッドはi等ではありません。
  • 状態を変更するメソッド:nextObject。

Erica SadunによるSwift Styleから   >計算プロパティとメソッド

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

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

Kotlin性質対規則>符号化機能上記のダニエルの回答を参照してください。

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


3

を使用しfuncます。オブジェクト指向プログラミングは、計算されたプロパティがなくても正常に機能します。計算/フィルタリングされた値を取得しているため、計算されたプロパティが正しいと感じる人もいます。しかし、ここに私の不満があります。あなたがそれをすると、読みやすさは価値がありますので、ヒットします。

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

event.countOfAttendees = 0; // not possible

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

event.countOfAttendees()

動作オブジェクトであれば、データ構造のように見えるのではなく、動作するように見えるはずだと思います。あなたのオブジェクトが愚かで、振る舞いがない場合、なぜそれをカプセル化しようとしますか?その場合は、出席者を公開するだけでも構いません

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