개인 클래스 메소드를 작성하는 방법은 무엇입니까?
개인 클래스 메소드를 작성하는 이러한 접근 방식은 어떻게 작동합니까?
class Person
def self.get_name
persons_name
end
class << self
private
def persons_name
"Sam"
end
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"
그러나 이것은하지 않습니다 :
class Person
def self.get_name
persons_name
end
private
def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
private
명시 적 객체 (귀하의 경우 self
) 에서 메소드를 정의하는 경우 작동하지 않는 것 같습니다 . private_class_method
클래스 메소드를 개인용 (또는 설명 된대로)으로 정의 하는 데 사용할 수 있습니다 .
class Person
def self.get_name
persons_name
end
def self.persons_name
"Sam"
end
private_class_method :persons_name
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
또는 (ruby 2.1+에서), 메소드 정의는 메소드 이름의 심볼을 반환하기 때문에 다음과 같이 사용할 수도 있습니다 :
class Person
def self.get_name
persons_name
end
private_class_method def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
루비의 그런 행동은 정말 실망입니다. 개인 섹션 self.method로 이동하면 개인 섹션이 아닙니다. 그러나 클래스 << self로 옮기면 갑자기 작동합니다. 역겨워 요.
아마 혼란스럽고, 좌절하면 좋지만 역겨운 것은 아닙니다.
It makes perfect sense once you understand Ruby's object model and the corresponding method lookup flow, especially when taking into consideration that private
is NOT an access/visibility modifier, but actually a method call (with the class as its recipient) as discussed here... there's no such thing as "a private section" in Ruby.
To define private instance methods, you call private
on the instance's class to set the default visibility for subsequently defined methods to private... and hence it makes perfect sense to define private class methods by calling private
on the class's class, ie. its metaclass.
Other mainstream, self-proclaimed OO languages may give you a less confusing syntax, but you definitely trade that off against a confusing and less consistent (inconsistent?) object model without the power of Ruby's metaprogramming facilities.
By default all class methods are public. To make them private you can use Module#private_class_method like @tjwallace wrote or define them differently, as you did:
class << self
private
def method_name
...
end
end
class << self
opens up self's singleton class, so that methods can be redefined for the current self object. This is used to define class/module ("static") method. Only there, defining private methods really gives you private class methods.
Just for the completeness, we can also avoid declaring private_class_method in a separate line. I personally don't like this usage but good to know that it exists.
private_class_method def self.method_name
....
end
I too, find Ruby (or at least my knowledge of it) short of the mark in this area. For instance the following does what I want but is clumsy,
class Frob
attr_reader :val1, :val2
Tolerance = 2 * Float::EPSILON
def initialize(val1, val2)
@val2 = val1
@val2 = val2
...
end
# Stuff that's likely to change and I don't want part
# of a public API. Furthermore, the method is operating
# solely upon 'reference' and 'under_test' and will be flagged as having
# low cohesion by quality metrics unless made a class method.
def self.compare(reference, under_test)
# special floating point comparison
(reference - under_test).abs <= Tolerance
end
private_class_method :compare
def ==(arg)
self.class.send(:compare, val1, arg.val1) &&
self.class.send(:compare, val2, arg.val2) &&
...
end
end
My problems with the code above is that the Ruby syntax requirements and my code quality metrics conspire to made for cumbersome code. To have the code both work as I want and to quiet the metrics, I must make compare() a class method. Since I don't want it to be part of the class' public API, I need it to be private, yet 'private' by itself does not work. Instead I am force to use 'private_class_method' or some such work-around. This, in turn, forces the use of 'self.class.send(:compare...' for each variable I test in '==()'. Now that's a bit unwieldy.
Instance methods are defined inside a class definition block. Class methods are defined as singleton methods on the singleton class of a class, also informally known as the "metaclass" or "eigenclass". private
is not a keyword, but a method (Module#private).
This is a call to method self#private
/A#private
which "toggles" private access on for all forthcoming instance method definitions until toggled otherwise:
class A
private
def instance_method_1; end
def instance_method_2; end
# .. and so forth
end
As noted earlier, class methods are really singleton methods defined on the singleton class.
def A.class_method; end
Or using a special syntax to open the definition body of the anonymous, singleton class of A:
class << A
def class_method; end
end
The receiver of the "message private" - self - inside class A
is the class object A. self inside the class << A
block is another object, the singleton class.
The following example is in reality calling two different methods called private, using two different recipients or targets for the call. In the first part, we define a private instance method ("on class A"), in the latter we define a private class method (is in fact a singleton method on the singleton class object of A).
class A
# self is A and private call "A.private()"
private def instance_method; end
class << self
# self is A's singleton class and private call "A.singleton_class.private()"
private def class_method; end
end
end
Now, rewrite this example a bit:
class A
private
def self.class_method; end
end
Can you see the mistake [that Ruby language designers] made? You toggle on private access for all forthcoming instance methods of A, but proceed to declare a singleton method on a different class, the singleton class.
As of ruby 2.3.0
class Check
def self.first_method
second_method
end
private
def self.second_method
puts "well I executed"
end
end
Check.first_method
#=> well I executed
참고URL : https://stackoverflow.com/questions/4952980/how-to-create-a-private-class-method
'Programing' 카테고리의 다른 글
mysql 사용자가 user / local / mysql / data 디렉토리를 소유하고 있지 않다는 경고 (0) | 2020.05.05 |
---|---|
각 측면에 2 개의 y 축과 다른 스케일이있는 ggplot (0) | 2020.05.05 |
HEAD 커밋 ID를 표시하는 Git 명령? (0) | 2020.05.05 |
Visual Studio 2013에서 기존 솔루션을 GitHub에 추가하는 방법 (0) | 2020.05.05 |
튜플 목록을 개별 목록으로 압축 해제하는 방법은 무엇입니까? (0) | 2020.05.05 |