21

これはほとんど哲学的な質問です。S4オブジェクトのスロットに直接アクセスしたり、スロットを設定したりするのは悪いこと@ですか?

これは悪い習慣であり、ユーザーは「アクセサー」S4メソッドを使用する必要があり、開発者はユーザーにこれらを提供する必要があると常に言われてきました。しかし、誰かがこの背後にある本当の取引を知っているかどうか知りたいですか?

パッケージを使用した例を次に示しspます(ただし、任意のS4クラスに一般化できます)。

> library(sp)
> foo <- data.frame(x = runif(5), y = runif(5), bar = runif(5))
> coordinates(foo) <- ~x+y
> class(foo)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"

> str(foo)
Formal class 'SpatialPointsDataFrame' [package "sp"] with 5 slots
  ..@ data       :'data.frame': 5 obs. of  1 variable:
  .. ..$ bar: num [1:5] 0.621 0.273 0.446 0.174 0.278
  ..@ coords.nrs : int [1:2] 1 2
  ..@ coords     : num [1:5, 1:2] 0.885 0.763 0.591 0.709 0.925 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : NULL
  .. .. ..$ : chr [1:2] "x" "y"
  ..@ bbox       : num [1:2, 1:2] 0.591 0.155 0.925 0.803
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : chr [1:2] "x" "y"
  .. .. ..$ : chr [1:2] "min" "max"
  ..@ proj4string:Formal class 'CRS' [package "sp"] with 1 slots
  .. .. ..@ projargs: chr NA

> foo@data
        bar
1 0.6213783
2 0.2725903
3 0.4458229
4 0.1743419
5 0.2779656
> foo@data <- data.frame(bar = letters[1:5], baz = runif(5))
> foo@data
  bar        baz
1   a 0.22877446
2   b 0.93206667
3   c 0.28169866
4   d 0.08616213
5   e 0.36713750
4

4 に答える 4

18

この質問では、stackoverflow-erがBioconductorIRangesオブジェクトendでスロットを見つけられない理由を尋ねます。結局のところ、、、およびアクセサとスロットがあります。答えは、ユーザーがクラスとインターフェイスする方法が、クラスの実装方法とは異なるためです。この場合、実装は、2つ(開発者までの2つ)だけで十分な場合に3つの値(開始、終了、幅)を格納することはスペース効率が良くないという単純な観察によって推進されます。インターフェイスと実装の間の相違の類似しているがより深い例は、他のS4オブジェクト、およびによって返されるもののような一般的なS3インスタンスに存在します。start()width()end()startwidthlm、クラスに格納されているデータが、特定のユーザーが最も関心を持っている可能性のある量を表すように調整されるのではなく、後続の計算に適している場合。そのlmインスタンスに到達して値を変更した場合、何も起こりません。coefficients要素。このインターフェースの実装からの分離により、開発者は、おそらく他の同様のクラスと共有される、合理的で一定のユーザーエクスペリエンスを提供するための多くの自由を得ることができますが、プログラミングに意味のある方法でクラスを実装(および実装を変更)することができます。

これは実際にはあなたの質問に答えるものではないと思いますが、開発者はユーザーがスロットに直接アクセスすることを期待しておらず、ユーザーは直接スロットアクセスがクラスと対話する適切な方法であることを期待すべきではありません。

于 2012-03-28T03:39:17.593 に答える
13

要するに、開発者はすべてのユースケースに対応するメソッドを提供する必要がありますが、実際にはこれは非常に困難であり、考えられるすべての使用法を網羅するのは複雑です。技術的に、そして私に関する限り、開発者が提供する以上のものが必要で、公開されていない機能を取得するために「@」を使用する必要がある場合、あなたは開発者です(GNUソフトウェアでは区別があいまいです)。

「ポリゴン」と「ライン」に必要な階層データ構造の複雑さは非常に単純な問題を引き起こすため、パッケージはこのsp質問をする良い例です。これが1つです:

ポリゴンとラインのcoordinates()メソッドは、オブジェクトごとに図心のみを返しますが、ポイントの場合は、オブジェクトからすべての「座標」を返しますが、これは「ポイント」が「1対1」であるためです。1つのオブジェクト、1つの座標、SpatialPointsとSpatialPointsDataFrameにも当てはまります。これは、LineとPolygon、LinesとPolygons、SpatialLinesとSpatialPolygons、またはSpatialLinesDataFrameとSpatialPolygonsDataFrameには当てはまりません。これらは本質的に、2つ以上の座標線トラックまたは3つ以上の座標のポリ「リング」で構成されています。すべてのマルチブランチSpatialPolygonからすべてのポリゴンのすべての頂点の座標を取得するにはどうすればよいですか?「@」を使用して開発者の構造を詳しく調べない限り、それはできません。

これを提供しなかったのは開発者の怠慢ですか?いいえ、利点は、特定のユーザーが後から見ることができる問題をはるかに上回ります。一般に、掘り下げることができるという事実は大きなボーナスですが、開発者の責任を自動的に引き受け、メソッドにラップせずに努力を共有することを選択した場合、状況はおそらく難しくなります。

于 2012-03-28T10:08:25.093 に答える
12

S4クラスの開発者として、私の意見は次のとおりです。

@を使用してスロットを読み取る場合は、自己責任で行ってください(Rで行うほとんどすべてのことと同様に、いくつかの有名な例については以下を参照してください)。そうは言っても、S4クラスのスロットは、実際には文書化されたインターフェースの一部です

私が見る経由でのアクセスの主な利点@は速度です:

> microbenchmark (accessor = wl (chondro), direct = chondro@wavelength)
Unit: nanoseconds
      expr    min       lq   median       uq    max
1 accessor 333431 341289.5 346784.5 366737.5 654219
2   direct    165    212.5    395.0    520.0   1440

(アクセサ関数は@wavelength、違いの原因となるスロットを返すことに加えて、妥当性チェックを行います。すべての適切なパブリックアクセサ関数が有効性を保証することを期待します)

タイムクリティカルな状況(たとえば、同じオブジェクトのサブセットの多くにアクセスする場合は、変更されていないオブジェクトの有効性を毎回チェックすることをスキップする価値があるかもしれません)で、クラスのスロットへの読み取りアクセスを使用することをお勧めします。私のパッケージのコードは主にスロットを直接読み取り、関数の最初とオブジェクトが無効になる可能性のある関数の最後で有効性を確認しました。@<-S4オブジェクトで動作するメソッドはオブジェクトが有効であることに依存できず、したがって純粋に読み取りアクセスを持つメソッドでさえ有効性チェックを行わなければならないため、有効性をチェックしない(R)設計決定は実際には莫大なオーバーヘッドを引き起こすと主張する人もいるかもしれません。

スロットへの書き込みアクセスについて考える場合は、自分が何をしているのかを本当に知っている必要があります。@<-有効性チェックは行いませ。公式の書き込みアクセサーが行う必要があります。また、書き込みアクセサーは、オブジェクトの状態の一貫性を維持するために、1つのスロットを更新するだけではありません。

したがって、スロットに書き込む場合は、地獄にいることに気づき、文句を言わないでください。;-)

これの哲学的な線に沿ってもう少し考えてみてください:私のパッケージはGPLの下で公開されています。私はあなたがあなたのニーズにコードを適応させることを許可するだけでなく、あなたがあなたのニーズに合わせてコードを開発/適応することを奨励したいと思います。実際、Rでは本当に簡単です。スロットへのアクセスを含め、すべてが通常のインタラクティブRセッションにすでに存在しています。これは、Rを非常に強力にするが、次のようなことを可能にする設計上の決定と完全に一致しています。

> T <- FALSE
> `+` <- `-`
> pi <- 3
> pi + 2
[1] 1
于 2012-03-28T12:42:11.057 に答える
10

一般に、オブジェクトのコンテンツをインターフェイスから分離することはプログラミングの良い習慣です。このウィキペディアの記事を参照してください。アイデアは、インターフェースを実装から分離することです。そうすることで、スクリプトなど、そのコードとインターフェースするコードに影響を与えることなく、実装を大幅に変更できます。したがって、を使用@すると、堅牢性の低いコードが作成され、数年以内に機能する可能性が低くなります。たとえば、sp@ mdsummerで言及されている-packageでは、速度や知識の進歩により、ポリゴンの格納方法の実装が変更される可能性があります。を使用する@と、コードが機能しなくなります。インターフェースを使用すると、コードは引き続き機能します。もちろん、インターフェースも変更された場合を除きます。ただし、実装の変更は、インターフェイスの変更よりもはるかに可能性が高くなります。

于 2012-03-28T13:02:53.590 に答える