0

ゲッターメソッドは、同じ名前のローカル変数がない限り、明示的なレシーバーなしで使用できます。

class A; attr_reader :foo end
A.new.instance_eval do
  @foo = :foo
  p foo
end
# => :foo

これは、あいまいさがある場合は常にメソッド呼び出しとしての解釈よりもローカル変数としての解釈が優先されるという原則により、同じ名前のローカル変数が存在する場合には成立しません。

class A; attr_reader :foo end
A.new.instance_eval do
  foo = :bar
  @foo = :foo
  p foo
end
# => :bar

ただし、問題の式の前に同じ名前のローカル変数が割り当てられていない場合でも、明示的なレシーバーなしではセッターメソッドを使用できません。

class A; attr_writer :foo end
A.new.instance_eval do
  foo = :foo  # <= No local variable named `foo` has been assigned before this point
  p @foo
end
# => nil

セッターメソッドのこの「アンチプライベート」プロパティはどのように正当化されますか?

4

3 に答える 3

5

If ruby interpreted your assignment in your last statement as an assignment to self, you would have no way left to set a local variable.

The way it is leaves no ambiguity for the interpreter to deal with: assignments without self are always local variables, assignments to self are always trying to use a writer on the object.


If it were the other way around

The interpreter would have to look up the contexts writer methods and assign it via the writer if there is one, which almost certainly would have a negative impact on performance

class A
  attr_writer :foo
end

A.new.instance_eval do
  # for each of these assignments, the interpreter has to look up if there's
  # a writer method defined
  foo = 'bar' 
  bar = 'baz'
  fib = 'buz'
end

It would also leave the programmer with the rather stupid task to find out every setter method of the context he's in before assigning local variables to make absolutely sure he does not unintentionally use a setter.

class C
  attr_writer :something
end

class B < C
  attr_writer :foo
end

class A < B
  attr_writer :bar
end

A.new.instance_eval
  something = 'something' 
  #you just (almost certainly with no intention) assigned a value to an attribute
end

Also, your question reads:

setter methods cannot be used without an explicit receiver even when a local variable with the same name is not assigned prior to the expression in question:

If it were the other way around, you could not assign a local variable with the same name prior to the expression in question, because the assignment would use the setter (as stated in the first paragraph of this answer)

Concerning the implementation / the access to variables the attribute methods use: Getter and Setters work with instance variables. So, for example attr_accessor actually defines something like this:

 def foo
   @foo
 end

 def foo=(data)
   @foo = data
 end

So, the attribute is declared as a instance variable and not as a local variable, why should the programmer be able to assign it like a local variable? This would leave the wrong impression that you could assign instance variables of an object via assigning local variables. If ruby would do this, it would almost certainly lead to a serious memory management problem. To make it short: foo = 'bar' and @foo = 'bar' are not the same, and exactly because the attr methods use @foo = 'bar', you can not call them via using foo = 'bar'.

于 2013-01-30T12:15:26.800 に答える
1

@sawa さんがようやく「反私的」の意味を明確にしたと思います。

澤さんのコメント:

プライベートとは、明示的な受信者を持つことができないことを意味します。それを否定すると、明示的な受信者がいる可能性がありますが、これは私が言及しているものではありません。メソッドに明示的なレシーバーが必要な場合について言及していますが、これは非公開に反します。あなたは混乱していると思います。

「非私的」と「非私的」は標準的な用語ではなく、意味もすぐに明らかではなかったため、他のすべてのコメント投稿者と同様に、私は混乱しました。

元の質問の意味は次のとおりだと思います:「セッターは明示的なレシーバーを必要とし、明示的なレシーバーを禁止するのでprivateprivate、どうすればprivateセッターを呼び出すことができますprivateか? 」"。

Jörg W Mittag は、通常の規則に対する例外をprivate雄弁に説明します。基本的に、セッターselfはプライベートであっても呼び出すことができます。これは、セッターを呼び出す方法が他にないためです (面倒な を使用しない限りsend)。

したがって、セッターの明示的なレシーバーの要件はprivate、ルールの例外のためだけに、セッターの存在と完全に互換性があります。

于 2013-11-01T21:09:54.283 に答える
-1

Beat Richartz の回答はすでにかなり完全ですが、提案している動作について 1 つのポイントを強調したいと思います。

あなたの質問には、次のサンプル コードがあります。

class A; attr_writer :foo end
A.new.instance_eval do
  foo = :foo  # <= No local variable named `foo` has been assigned before this point
  p @foo
end

割り当てがセッターメソッドを呼び出すことを提案しています。fooそして、ローカル変数がまだ割り当てられていない場合に、これが発生することを望みます。

しかし、その前にローカルを割り当てるには、どの構文使用しますか?

レシーバーレス割り当てがセッターを呼び出すことを意味する場合(存在する場合)、「セッターがあるかどうかに関係なく、このローカル変数を割り当てるfoo = :foo」ことを意味する別の構文構造が必要になります。

私は正直にあなたの提案を聞きたいです(私は皮肉ではありません). 言語設計に関する別の見解を聞くことは興味深いでしょう。

あなたのやり方が必ずしも現在のルビーのやり方よりも「悪い」と言っているわけではありません。しかし、ある時点で、言語設計者はあいまいな状況に対するデフォルトの動作を決定する必要があり、Matz は受信者なしの割り当てがローカルを割り当てることを決定しました。

于 2013-11-01T18:25:39.807 に答える