이 기사를 읽기 전에 Ruby의 액세스 제어가 다음과 같이 작동한다고 생각했습니다.
public
– 모든 객체에 의해 액세스 할 수 있습니다 (예를 들어Obj.new.public_method
)protected
-객체 자체와 하위 클래스에서만 액세스 할 수 있습니다private
-protected와 동일하지만 메소드가 서브 클래스에 존재하지 않습니다.
그러나 것으로 보인다 protected
와 private
같은 역할을 전화 할 수 없다는 사실을 제외하고 private
명시 적 수신기 방법 (즉, self.protected_method
작품,하지만 self.private_method
하지 않습니다).
요점이 뭐야? 명시 적 리시버로 메소드를 호출하지 않으려는 시나리오는 언제입니까?
답변
protected
메소드는 정의 클래스 또는 해당 서브 클래스의 모든 인스턴스에서 호출 할 수 있습니다.
private
메소드는 호출 객체 내에서만 호출 할 수 있습니다. 다른 인스턴스의 프라이빗 메서드에 직접 액세스 할 수 없습니다.
다음은 간단한 실제 예입니다.
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
private
여기 있을 수 없습니다 . 그것은해야합니다 protected
당신이 명시 적으로 수신기를 지원하기 위해 필요하기 때문이다. 일반적인 내부 헬퍼 메소드는 일반적으로 private
이와 같이 호출 할 필요가 없기 때문에 일반적 일 수 있습니다 .
이것은 Java 또는 C ++의 작동 방식과 다르다는 점에 유의해야합니다. private
Ruby protected
에서 하위 클래스가 메소드에 액세스 할 수 있다는 점에서 Java / C ++에서 와 유사합니다 . Ruby에서는 private
Java에서 와 같이 하위 클래스의 메소드에 대한 액세스를 제한 할 방법이 없습니다 .
루비에서의 가시성은 다음과 같은 방법으로 항상 메소드에 액세스 할 수 있기 때문에 대체로 “추천”입니다 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
암시.- iGEL은 다음과 같이 지적합니다. “하지만 한 가지 예외가 있습니다. age = 전용 메소드가 있다면, 로컬 변수와 분리하기 위해 자체적으로 호출 할 수 있습니다.”
- 때문에 루비 2.7
self
수신기가 명시 될 수self.some_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에서 개인용 인 경우 명시 적 수신자 (오브젝트)가 메소드를 호출 할 수 없습니다. 암시 적으로 만 호출 할 수 있습니다. 이 클래스는 서브 클래스뿐만 아니라 해당 클래스가 설명 된 클래스에 의해 내재적으로 호출 될 수 있습니다.
다음 예제는 더 잘 설명합니다.
1) 개인 메소드 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
2) 양서류라는 동물의 서브 클래스 :
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
보다시피, private 메소드는 암시 적으로 만 호출 할 수 있습니다. 명시적인 수신자가 호출 할 수 없습니다. 같은 이유로, 개인용 메소드는 정의 클래스의 계층 외부에서 호출 될 수 없습니다.
루비에서 보호 된 메소드 :
메소드가 Ruby로 보호되는 경우, 정의 클래스와 해당 서브 클래스 둘 다에 의해 내재적으로 호출 될 수 있습니다. 또한 수신자가 자체 클래스이거나 자체 클래스와 동일한 클래스 인 경우 명시 적 수신자가 호출 할 수도 있습니다.
1) protected 메소드 protect_me를 가진 Animal 클래스
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
2) 동물 계급에서 물려받은 포유류 계급
class Mammal < Animal
def mammal_call
protect_me
end
end
이 경우
n= Mammal.new
n.mammal_call #=> protect_me called from Mammal
3) 동물 계급 (포유류 계급과 동일)에서 물려받은 양서류 계급
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
4) Tree라는 클래스
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
}
}
따라서 호출자가 동일한 클래스의 다른 인스턴스 인 경우 실제로는 “외부”에서 개인용 메소드에 액세스 할 수 있습니다. 이것은 실제로 그것이 사적인 것이 아닌 것처럼 보입니다.
반면에 루비에서는 프라이빗 메소드가 실제로는 현재 인스턴스에만 프라이빗으로 사용됩니다. 이것이 명시적인 수신자 옵션을 제거하는 것입니다.
다른 한편으로, 루비가 어쨌든 그들을 둘러 볼 수있는 방법을 제공한다는 점에서 루비 커뮤니티에서는 이러한 가시성 컨트롤을 전혀 사용하지 않는 것이 일반적이라는 것을 분명히 지적해야합니다. 자바 세계와는 달리, 모든 것을 접근 가능하게 만들고 다른 개발자가 일을 망치지 않도록 믿습니다.
답변
루비에서 서브 클래스로 프라이빗 메소드에 액세스 할 수있는 이유 중 하나는 클래스를 사용한 루비 상속이 모듈 포함에 비해 설탕이 얇기 때문입니다.
http://ruby-doc.org/core-2.0.0/Class.html
이것이 의미하는 바는 기본적으로 서브 클래스가 부모 클래스를 “포함” 하여 프라이빗 함수를 포함한 부모 클래스의 함수 가 서브 클래스에도 효과적으로 정의된다는 것입니다.
다른 프로그래밍 언어에서 메서드를 호출하면 메서드 이름을 부모 클래스 계층으로 버블 링하고 메서드에 응답하는 첫 번째 부모 클래스를 찾습니다. 반대로 Ruby에서는 부모 클래스 계층 구조가 여전히 존재하지만 부모 클래스의 메서드는 하위 클래스의 메서드 목록에 직접 포함됩니다.
답변
Ruby와 Java의 액세스 제어 비교 : 메소드가 Java에서 개인용으로 선언 된 경우 동일한 클래스 내의 다른 메소드 만 액세스 할 수 있습니다. 보호 된 것으로 선언 된 메소드는 동일한 패키지 내에 존재하는 다른 클래스 및 다른 패키지에있는 클래스의 서브 클래스에 의해 액세스 될 수 있습니다. 방법이 공개되면 모든 사람이 볼 수 있습니다. 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
정의 된 클래스 계층 외부에서는 private 메소드를 호출 할 수 없습니다.
private과 같이 암시 적 수신자를 사용하여 보호 된 메소드를 호출 할 수 있습니다. 또한 수신자가 “self”또는 “같은 클래스의 객체”인 경우 명시 적 수신자 (보호 된 메소드)에 의해 protected 메소드를 호출 할 수도 있습니다.
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
요약
공개 : 공개 메소드는 최대 가시성을 갖습니다.
Protected : private과 같이 암시 적 수신자를 사용하여 protected 메서드를 호출 할 수 있습니다. 또한 수신자가 “self”또는 “같은 클래스의 객체”인 경우 명시 적 수신자 (보호 된 메소드)에 의해 protected 메소드를 호출 할 수도 있습니다.
개인 : Ruby의 개인 메소드의 경우 명시 적 수신자로 호출 할 수 없습니다. 암시 적 수신자를 사용하여 전용 메소드를 호출 할 수 있습니다. 이것은 또한 선언 된 클래스와이 클래스의 모든 서브 클래스에서 전용 메소드를 호출 할 수 있음을 의미합니다.
답변
First Three types of access specifiers and those define thier scope.
1.Public -> Access anywhere out side the class.
2.Private -> Can not access outside the class.
3.Protected -> This Method not access anywhere this method define
scope.
But i have a solution for this problem for all method how to access explain in depth.
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.new ( “test”)
- p test.name
- p test.add_two (3)
- 목록 항목
- p test.view_address
- pr = Result.new ( “”)
- 새 사용자