개인 클래스 메소드를 만드는 방법은 무엇입니까?
개인 클래스 메소드를 만드는 이러한 접근 방식은 어떻게 작동합니까?
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
를 사용하여 클래스 메소드를 비공개(또는 설명한 대로)로 정의할 수 있습니다.
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
ExiRe가 작성한 내용:
루비의 그런 행동은 정말 실망스럽습니다.제 말은 당신이 개인 구역으로 이동한다면요.메소드는 비공개가 아닙니다.하지만 클래스 << self로 옮기면 갑자기 작동합니다.정말 역겹습니다.
그것을 혼란스럽게 하는 것은 아마도, 좌절하게 하는 것은 당연하지만, 역겨운 것은 확실히 그렇지 않습니다.
Ruby의 객체 모델과 해당 메소드 룩업 흐름을 이해한 후에는 특히 다음을 고려할 때 완벽하게 말이 됩니다.private
액세스/가시성 수정자가 아니라 실제로는 클래스를 수신자로 하는 메서드 호출입니다.루비에는 "개인 섹션" 같은 것이 없습니다.
개인 인스턴스 메서드를 정의하려면 다음을 호출합니다.private
인스턴스 클래스에서 후속으로 정의된 메서드에 대한 기본 가시성을 개인...으로 설정합니다.따라서 호출을 통해 개인 수업 방법을 정의하는 것은 완벽하게 이치에 맞습니다.private
수업 중, 즉 메타 수업입니다.
다른 주류의 자칭 OOO 언어는 덜 혼란스러운 구문을 제공할 수도 있지만 Ruby의 메타프로그래밍 기능이 없는 혼란스럽고 일관성이 떨어지는(불일치적이지 않은) 객체 모델과 비교하면 분명 차이가 있습니다.
기본적으로 모든 클래스 메서드는 공용입니다.@tjwallace가 작성한 것처럼 Module#private_class_method를 사용하거나 다음과 같이 다르게 정의할 수 있습니다.
class << self
private
def method_name
...
end
end
class << self
현재 self 객체에 대해 메서드를 재정의할 수 있도록 self의 singleton 클래스를 엽니다.클래스/모듈("정적") 메서드를 정의하는 데 사용됩니다.여기서만 개인 메소드를 정의하면 실제로 개인 클래스 메소드가 제공됩니다.
또한 완전성을 위해 private_class_method를 별도의 행으로 선언하지 않아도 됩니다.저는 개인적으로 이 사용법이 마음에 들지 않지만 존재한다는 것을 알게 되어 기쁩니다.
private_class_method def self.method_name
....
end
인스턴스 메서드는 클래스 정의 블록 내에서 정의됩니다.클래스 메소드는 클래스의 싱글톤 클래스에서 싱글톤 메소드로 정의되며, 비공식적으로 "메타 클래스" 또는 "아이겐 클래스"라고도 합니다. private
키워드가 아니라 메서드(Module#private)입니다.
은 메소드 메드니다입에 입니다.self#private
/A#private
그렇지 않으면 전환될 때까지 이후의 모든 인스턴스 메서드 정의에 대해 개인 액세스를 "슬립"합니다.
class A
private
def instance_method_1; end
def instance_method_2; end
# .. and so forth
end
앞서 언급한 바와 같이 클래스 메소드는 실제로 싱글톤 클래스에 정의된 싱글톤 메소드입니다.
def A.class_method; end
또는 특수 구문을 사용하여 A의 익명 싱글톤 클래스의 정의 본문을 엽니다.
class << A
def class_method; end
end
"개인 메시지" 수신자 - 자체 내부class A
는 클래스 개체 A. A. self입니다.class << A
블록은 또 다른 객체인 싱글톤 클래스입니다.
다음 예제에서는 실제로 두 개의 서로 다른 수신자 또는 대상을 사용하여 비공개라고 하는 두 가지 다른 메서드를 호출합니다.첫 번째 부분에서는 개인 인스턴스 방법("A 클래스")을 정의하고, 후자에서는 개인 클래스 방법(사실 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
다음 예제를 조금 다시 작성합니다.
class A
private
def self.class_method; end
end
[루비 언어 디자이너]가 저지른 실수를 볼 수 있습니까?이후 A의 모든 인스턴스 메서드에 대해 개인 액세스를 설정하고 다른 클래스인 싱글톤 클래스에 싱글톤 메서드를 선언합니다.
저도 루비(또는 적어도 제가 아는 지식)가 이 분야에서 부족하다는 것을 발견합니다.예를 들어, 다음은 내가 원하는 것을 하지만 서투릅니다.
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
위 코드의 문제는 Ruby 구문 요구 사항과 코드 품질 메트릭이 공모하여 번거로운 코드를 만든다는 것입니다.코드가 원하는 대로 작동하고 메트릭을 조용하게 하려면 compare()를 클래스 메소드로 만들어야 합니다.클래스의 공용 API에 포함되는 것을 원하지 않기 때문에 비공개로 해야 하지만 '전용' 자체는 작동하지 않습니다.대신 'private_class_method' 또는 이러한 해결 방법을 사용해야 합니다.이렇게 하면 '==test'에서 테스트하는 각 변수에 대해 'self.class.send(:test...')를 강제로 사용할 수 있습니다.이제 그것은 좀 다루기 어렵습니다.
루비는 해결책이 부족한 것 같습니다.설명하려면 개인 클래스 메서드에 대한 액세스를 보여주는 간단한 C++ 예제로 시작합니다.
#include <iostream>
class C
{
public:
void instance_method(void)
{
std::cout << "instance method\n";
class_method(); // !!! LOOK !!! no 'send' required. We can access it
// because 'private' allows access within the class
}
private:
void static class_method(void) { std::cout << "class method\n"; }
};
int main()
{
C c;
c.instance_method(); // works
// C::class_method() does not compile - it's properly private
return 0;
}
위의 실행
% ./a.out
instance method
class method
이제 Ruby는 동등한 것을 제공하지 않는 것 같습니다.제 생각에 루비의 규칙은 개인적인 방법은 수신기로 접근해서는 안 된다는 것입니다.그것은,
inst.pvt_method # FAILS
pvt_method # WORKS only within the class (good)
개인 인스턴스 메소드에는 문제가 없지만 개인 클래스 메소드에는 문제가 발생합니다.
저는 루비가 다음과 같이 기능하기를 원합니다.
class C
def instance_method
STDOUT << "instance method\n"
# Simple access to the private class method would be nice:
class_method # DOES NOT WORK. RUBY WON'T FIND THE METHOD
C.class_method # DOES NOT WORK. RUBY WON'T ALLOW IT
# ONLY THIS WORKS. While I am happy such capability exists I think
# the way 'send' should be used is when the coder knows he/she is
# doing a no-no. The semantic load on the coder for this is also
# remarkably clumsy for an elegant language like ruby.
self.class.send(:class_method)
end
private_class_method def self.class_method() STDOUT << "class method\n"; end
end
하지만, 아아, 위의 것들은 작동하지 않습니다.더 좋은 방법을 아는 사람이 있습니까?
메서드 앞에 'send'를 보면 코드가 API 설계자의 의도를 위반하는 것이 분명하지만, 이 경우 설계자는 클래스의 인스턴스 메서드를 개인 클래스 메서드라고 부릅니다.
언급URL : https://stackoverflow.com/questions/4952980/how-to-create-a-private-class-method
'programing' 카테고리의 다른 글
목록 모음에서 메서드 선택 (0) | 2023.06.17 |
---|---|
테이블에 명명된 검사 제약 조건 추가 (0) | 2023.06.12 |
TypeError: 'NoneType' 개체는 Python에서 볼 수 있습니다. (0) | 2023.06.12 |
C에서 **를 사용할 때의 차이점 (0) | 2023.06.12 |
업데이트된 수명 주기 후크의 Vuex 상태 업데이트 (0) | 2023.06.12 |