왜 Ruby는 개인적인 방법과 보호된 방법을 모두 가지고 있습니까?
이 기사를 읽기 전에는 Ruby의 액세스 제어가 다음과 같이 작동한다고 생각했습니다.
public
모든개예체예(:)로 수 .Obj.new.public_method
)protected
는 객체 자체 수 , 하위 는 물론 하위 클래스에서 수 있습니다.private
하위 .
하지만, 다음과 같이 보입니다.protected
그리고.private
전화를 할 수 없다는 사실을 제외하고는 똑같이 행동합니다.private
명적수시있즉방는법가기신즉▁with방(법,▁an,self.protected_method
작하지만동,▁works동작만.self.private_method
하지 않음).
이게 무슨 의미가 있습니까?명시적 수신기를 사용하여 메서드를 호출하지 않으려는 시나리오는 언제입니까?
protected
메서드는 정의 클래스 또는 해당 하위 클래스의 인스턴스에 의해 호출될 수 있습니다.
private
메서드는 호출 개체 내에서만 호출할 수 있습니다.다른 인스턴스의 개인 메서드에 직접 액세스할 수 없습니다.
다음은 간단한 실용적인 예입니다.
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
가 될 수 .private
요기일 예요. 틀림없이protected
명시적 수신기를 지원하기 위해 필요하기 때문입니다.일반적인 내부 도우미 방법은 다음과 같습니다.private
그들은 결코 이렇게 불릴 필요가 없기 때문입니다.
이것은 Java 또는 C++의 작동 방식과는 다릅니다. private
는 루비경유사다니합우와의와 합니다.protected
하위 클래스에서 메서드에 액세스할 수 있는 Java/C++입니다.루비처럼 클래스에서 를 제한할 수 .private
자바로
은 Ruby를 에 항상 액세스할 있기 에 대부분 "권장"입니다.send
:
irb(main):001:0> class A
irb(main):002:1> private
irb(main):003:1> def not_so_private_method
irb(main):004:2> puts "Hello World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> foo = A.new
=> #<A:0x31688f>
irb(main):009:0> foo.send :not_so_private_method
Hello World
=> nil
차이
- 누구나 공용 메소드를 호출할 수 있습니다.
- 보호된 메서드를 호출하거나 클래스의 다른 구성원(또는 하위 클래스)이 외부에서 보호된 메서드를 호출할 수 있습니다.아무도 할 수 없습니다.
- 메서드만 호출할 수 . 메서드는 할 수 입니다.
self
당신도 전화를 할 수 없습니다.self.some_private_method
꼭전보요세에 전화해야 .private_method
와 함께self
묵시의
루비에서 이러한 구별은 한 프로그래머가 다른 프로그래머에게 조언하는 것에 불과합니다.비공개 방법은 "나는 이것을 바꿀 권리를 보유한다; 그것에 의존하지 마라"라고 말하는 방법입니다.하지만 당신은 여전히 날카로운 가위를 가지고 있습니다.send
원하는 방법을 호출할 수 있습니다.
간단한 자습서
# dwarf.rb
class Dwarf
include Comparable
def initialize(name, age, beard_strength)
@name = name
@age = age
@beard_strength = beard_strength
end
attr_reader :name, :age, :beard_strength
public :name
private :age
protected :beard_strength
# Comparable module will use this comparison method for >, <, ==, etc.
def <=>(other_dwarf)
# One dwarf is allowed to call this method on another
beard_strength <=> other_dwarf.beard_strength
end
def greet
"Lo, I am #{name}, and have mined these #{age} years.\
My beard is #{beard_strength} strong!"
end
def blurt
# Not allowed to do this: private methods can't have an explicit receiver
"My age is #{self.age}!"
end
end
require 'irb'; IRB.start
그럼 도망칠 수 있어요ruby dwarf.rb
다음을 수행합니다.
gloin = Dwarf.new('Gloin', 253, 7)
gimli = Dwarf.new('Gimli', 62, 9)
gloin > gimli # false
gimli > gloin # true
gimli.name # 'Gimli'
gimli.age # NoMethodError: private method `age'
called for #<Dwarf:0x007ff552140128>
gimli.beard_strength # NoMethodError: protected method `beard_strength'
called for #<Dwarf:0x007ff552140128>
gimli.greet # "Lo, I am Gimli, and have mined these 62 years.\
My beard is 9 strong!"
gimli.blurt # private method `age' called for #<Dwarf:0x007ff552140128>
Ruby의 개인 메서드:
메서드가 Ruby에서 비공개인 경우 명시적 수신기(개체)에서 호출할 수 없습니다.암시적으로만 호출할 수 있습니다.이 클래스는 에서 설명한 클래스와 이 클래스의 하위 클래스에 의해 암시적으로 호출될 수 있습니다.
다음 예를 통해 더 잘 알 수 있습니다.
개인 메서드 class_name이(가) 있는 동물 클래스입니다.
class Animal
def intro_animal
class_name
end
private
def class_name
"I am a #{self.class}"
end
end
이 경우:
n = Animal.new
n.intro_animal #=>I am a Animal
n.class_name #=>error: private method `class_name' called
양서류라고 불리는 동물의 하위 분류:
class Amphibian < Animal
def intro_amphibian
class_name
end
end
이 경우:
n= Amphibian.new
n.intro_amphibian #=>I am a Amphibian
n.class_name #=>error: private method `class_name' called
보시다시피 개인 메서드는 암시적으로만 호출할 수 있습니다.명시적 수신기에서는 호출할 수 없습니다.같은 이유로, 개인 메서드는 정의 클래스의 계층 외부에서 호출할 수 없습니다.
Ruby의 보호된 메서드:
메서드가 Ruby에서 보호되는 경우 정의 클래스와 하위 클래스 모두에서 메서드를 암시적으로 호출할 수 있습니다.또한 수신기가 자기 또는 자기와 동일한 클래스인 한 명시적 수신기에 의해 호출될 수 있습니다.
보호 메서드 protect_me가 있는 동물 클래스
class Animal
def animal_call
protect_me
end
protected
def protect_me
p "protect_me called from #{self.class}"
end
end
이 경우:
n= Animal.new
n.animal_call #=> protect_me called from Animal
n.protect_me #=>error: protected method `protect_me' called
동물 등급에서 상속된 포유류 등급
class Mammal < Animal
def mammal_call
protect_me
end
end
이 경우
n= Mammal.new
n.mammal_call #=> protect_me called from Mammal
동물 분류에서 물려받은 양서류 분류(포유류 분류와 동일)
class Amphibian < Animal
def amphi_call
Mammal.new.protect_me #Receiver same as self
self.protect_me #Receiver is self
end
end
이 경우
n= Amphibian.new
n.amphi_call #=> protect_me called from Mammal
#=> protect_me called from Amphibian
트리라는 클래스
class Tree
def tree_call
Mammal.new.protect_me #Receiver is not same as self
end
end
이 경우:
n= Tree.new
n.tree_call #=>error: protected method `protect_me' called for #<Mammal:0x13410c0>
Java의 개인 방법을 고려합니다.물론 동일한 클래스 내에서 호출할 수 있지만 동일한 클래스의 다른 인스턴스에서도 호출할 수 있습니다.
public class Foo {
private void myPrivateMethod() {
//stuff
}
private void anotherMethod() {
myPrivateMethod(); //calls on self, no explicit receiver
Foo foo = new Foo();
foo.myPrivateMethod(); //this works
}
}
그래서 -- 만약 발신자가 제 클래스의 다른 인스턴스라면 -- 말하자면, 제 개인적인 방법은 "외부"에서 접근할 수 있습니다.이것은 사실 그것을 그렇게 사적인 것으로 보이지 않게 만듭니다.
반면에 Ruby에서 Private 메서드는 현재 인스턴스에만 Private로 지정됩니다.이것이 명시적 수신기의 옵션을 제거하는 것입니다.
다른 한편으로, 저는 루비 커뮤니티에서 이러한 가시성 컨트롤을 전혀 사용하지 않는 것이 꽤 흔하다는 것을 분명히 지적해야 합니다. 루비는 어쨌든 이러한 컨트롤을 피할 수 있는 방법을 제공하기 때문입니다.자바 세계와는 달리, 모든 것을 접근 가능하게 하고 다른 개발자들이 일을 망치지 않도록 신뢰하는 경향이 있습니다.
뭐가 달라요?
개인 방법 설명
@freddie = Person.new
@freddie.hows_it_going?
# => "oh dear, i'm in great pain!"
class Person
# public method
def hows_it_going?
how_are_your_underpants_feeling?
end
private
def how_are_your_underpants_feeling? # private method
puts "oh dear, i'm in great pain!"
end
end
우리는 프레디에게 공개적인 방법으로 상황이 어떻게 진행되고 있는지 물어볼 수 있습니다.그것은 완벽하게 타당합니다.그리고 그것은 정상적이고 받아들여집니다.
하지만... 프레디의 팬티 상황을 알 수 있는 유일한 사람은 프레디 자신입니다.아무도 모르는 사람들이 프레디의 팬티 속으로 손을 뻗는 것은 좋지 않을 것입니다. 아니요, 그건 매우 사적인 일입니다. 그리고 우리는 사적인 것을 외부에 노출시키고 싶지 않습니다.다시 말해서, 우리는 세계의 어떤 발신자에게도 가변적인 데이터를 노출시키고 싶지 않을 수 있습니다.누군가가 값을 변형시킬 수도 있고, 우리는 그 벌레가 어디서 왔는지 알아내려고 애쓰며 고통의 세계에 빠질 것입니다.
@freddie.how_are_your_underpants_feeling?
# => # NoMethodError: private method `how_are_your_underpants_feeling?' called
보호된 방법 설명
고려 사항:
class Person
protected
def hand_over_the_credit_card! # protected method
puts "Lawd have mercy. Whatever. Here it is: 1234-4567-8910"
end
end
class Rib < Person
end
class Wife < Rib # wife inherits from Rib
def i_am_buying_another_handbag_with_your_card(husband)
husband.hand_over_the_credit_card! # equalityInAction
end
end
@husband = Person.new
@mrs = Wife.new
@mrs.i_am_buying_another_handbag_with_your_card(@husband)
# => puts "Lawd have mercy. Whatever. Here it is: 1234-4567-8910"
우리는 어느 정도 괜찮습니다.mrs
우리의 신용카드 세부 정보를 얻는 것, 주어진.mrs
사람으로부터 물려받은 우리의 살점입니다. 그래서 그녀는 신발 등에 그것을 불 수 있지만, 우리는 무작위의 개인이 우리의 신용카드 세부 정보에 접근하는 것을 원하지 않습니다.
하위 클래스 밖에서 이 작업을 수행하려고 하면 실패합니다.
@mrs = Wife.new
@mrs.gimme_your_credit_card!
# => protected method hand_over_the_credit_card! called for #<Wife:0x00005567b5865818> (NoMethodError)
요약
- 개인 메서드는 "명시적 수신기" 없이 내부에서만 호출할 수 있습니다. (엄밀히 말하자면, 루비 마법을 조금 사용하여 개인 메서드에 액세스할 수 있지만, 현재로서는 무시하겠습니다.)
- 보호된 메서드를 하위 도메인 내에서 호출할 수 있습니다.
- 저는 여러분이 생생하게 기억할 수 있도록 예시/유용어를 사용했습니다.
Ruby의 하위 클래스에서 개인 메서드에 액세스할 수 있는 이유 중 일부는 클래스가 포함된 Ruby 상속이 모듈을 포함하는 얇은 설탕 코팅이기 때문입니다. 실제로 Ruby에서 클래스는 상속 등을 제공하는 일종의 모듈입니다.
http://ruby-doc.org/core-2.0.0/Class.html
이것이 의미하는 바는 기본적으로 하위 클래스가 상위 클래스를 "포함"하여 개인 기능을 포함한 상위 클래스의 기능이 하위 클래스에서도 효과적으로 정의된다는 것입니다.
다른 프로그래밍 언어에서 메소드 호출은 메소드 이름을 부모 클래스 계층 구조로 버블링하고 메소드에 응답하는 첫 번째 부모 클래스를 찾는 것을 포함합니다.반대로 Ruby에서는 부모 클래스 계층이 여전히 존재하는 동안 부모 클래스의 메서드는 하위 클래스의 메서드 목록에 직접 포함됩니다.
Java의 접근통제와 Ruby의 비교 : Java에서 method가 private로 선언된 경우 동일 클래스 내의 다른 method만 접근할 수 있습니다.메서드가 보호된 것으로 선언되면 동일한 패키지 내에 있는 다른 클래스와 다른 패키지에 있는 클래스의 하위 클래스에서 액세스할 수 있습니다.방법이 공개되면 모든 사람이 볼 수 있습니다.Java에서 액세스 제어 가시성 개념은 이러한 클래스가 상속/패키지 계층 구조의 위치에 따라 달라집니다.
Ruby에서는 상속 계층이나 패키지/모듈이 맞지 않습니다.어떤 객체가 메서드의 수신자인지에 대한 모든 것입니다.
Ruby의 개인 메서드의 경우 명시적 수신기로 호출할 수 없습니다.암시적 수신기를 사용하여 개인 메서드를 호출할 수 있습니다.
이는 또한 클래스 내에서 선언된 개인 메서드와 이 클래스의 모든 하위 클래스를 호출할 수 있음을 의미합니다.
class Test1
def main_method
method_private
end
private
def method_private
puts "Inside methodPrivate for #{self.class}"
end
end
class Test2 < Test1
def main_method
method_private
end
end
Test1.new.main_method
Test2.new.main_method
Inside methodPrivate for Test1
Inside methodPrivate for Test2
class Test3 < Test1
def main_method
self.method_private #We were trying to call a private method with an explicit receiver and if called in the same class with self would fail.
end
end
Test1.new.main_method
This will throw NoMethodError
정의된 클래스 계층 외부에서 개인 메서드를 호출할 수 없습니다.
보호된 메서드는 비공개와 마찬가지로 암시적 수신기를 사용하여 호출할 수 있습니다.또한 보호된 메서드는 수신기가 "자체" 또는 "동일한 클래스의 개체"인 경우에만 명시적 수신기에 의해 호출될 수 있습니다.
class Test1
def main_method
method_protected
end
protected
def method_protected
puts "InSide method_protected for #{self.class}"
end
end
class Test2 < Test1
def main_method
method_protected # called by implicit receiver
end
end
class Test3 < Test1
def main_method
self.method_protected # called by explicit receiver "an object of the same class"
end
end
InSide method_protected for Test1
InSide method_protected for Test2
InSide method_protected for Test3
class Test4 < Test1
def main_method
Test2.new.method_protected # "Test2.new is the same type of object as self"
end
end
Test4.new.main_method
class Test5
def main_method
Test2.new.method_protected
end
end
Test5.new.main_method
This would fail as object Test5 is not subclass of Test1
Consider Public methods with maximum visibility
요약
Public(공용): Public(공용) 메서드는 가시성이 최대입니다.
보호됨: 보호된 메서드는 비공개와 마찬가지로 암시적 수신기를 사용하여 호출할 수 있습니다.또한 보호된 메서드는 수신기가 "자체" 또는 "동일한 클래스의 개체"인 경우에만 명시적 수신기에 의해 호출될 수 있습니다.
비공개:Ruby의 개인 메서드의 경우 명시적 수신기로 호출할 수 없습니다.암시적 수신기를 사용하여 개인 메서드를 호출할 수 있습니다.이는 또한 클래스 내에서 선언된 개인 메서드와 이 클래스의 모든 하위 클래스를 호출할 수 있음을 의미합니다.
처음 세 가지 유형의 액세스 지정자와 그 범위를 정의합니다.
- 공용 -> 클래스 외부의 모든 위치에 액세스합니다.
- 비공개 -> 클래스 외부에서 액세스할 수 없습니다.
- 보호됨 -> 이 메서드는 범위를 정의하는 모든 위치에 액세스할 수 없습니다.
하지만 저는 이 문제에 대한 해결책을 가지고 있습니다. 어떻게 자세히 설명할 수 있는지에 대한 모든 방법에 대해서요.
class Test
attr_reader :name
def initialize(name)
@name = name
end
def add_two(number)
@number = number
end
def view_address
address("Anyaddress")
end
private
def address(add)
@add = add
end
protected
def user_name(name)
# p 'call method'
@name = name
end
end
class Result < Test
def new_user
user_name("test355")
end
end
- 개체 목록
- p test = Test.new("test")
- p test.name
- p test.add_2(3)
- 리스트 항목
- ptest.view_address
- pr = Result.new("")
- pr.new_user
언급URL : https://stackoverflow.com/questions/3534449/why-does-ruby-have-both-private-and-protected-methods
'programing' 카테고리의 다른 글
문자열에서 하위 문자열 제거 (0) | 2023.06.02 |
---|---|
스피너 선택 항목 텍스트를 가져오시겠습니까? (0) | 2023.06.02 |
사용 가능한 ID가 없음 - 관리자 요청 (0) | 2023.06.02 |
Spring data MongoDb: MappingMongoConverter remove_class (0) | 2023.06.02 |
릴리스 또는 디버그 모드인지 탐지하려면 어떻게 해야 합니까? (0) | 2023.06.02 |