루비를 아름답게 만드는 것: 메타프로그래밍
Ruby is making developers happy, productive and enjoying programming. - Yukihiro Matsumoto
많은 프레임워크가 있는 JS 세계 또는 Java와 그 모든 복잡성에서 왔을 수 있습니다.
중요한 소프트웨어를 구축하는 데 시간을 낭비하고 가능한 한 빨리 구체적인 결과를 얻고 싶다면 Ruby를 소개하겠습니다.
메타 프로그래밍의 개념을 소개하겠습니다.
루비를 처음 배웠을 때, 이것에 직면했을 때 말 그대로 마음이 흔들렸습니다.
Think about a program that can generate program itself. A program that can generate executable code without the help of a developer.
아니요, 공상 과학이 아니라 Ruby Metaprogramming입니다!
5살짜리에게 설명해야 한다면, 당신이 화창한 도시를 그리고 싶다고 상상해보세요. 펜을 들고 종이에 "Sunny City"라고 쓰세요. 버튼을 누르면 마법이 일어납니다. 그것이 바로 메타프로그래밍입니다.
이제 실제 개발자들에게 설명하겠습니다.
Ruby에서는 메서드에 대한 런타임 검사를 수행할 수 있습니다. 다른 한편으로 객체에 기능(이 방법이 있습니까?), 변수, 상수, 클래스 및 조상에 대해 물어볼 수 있습니다.
이 기사에서 나는 당신에게 respond_to? (?는 부울을 반환하는 메서드에 대한 Ruby 규칙입니다.) send 및 define_method. 그러나 method_missing, remove_method 및 undef_method와 같은 훨씬 더 많은 것이 있습니다.
이 세 가지 방법을 설명하고 마지막으로 놀라운 예를 보여 드리겠습니다.
respond_to?() 메서드
이 메서드는 Ruby를 사용하지 않는 사람들을 위해 특정 메시지를 처리할 수 있는지 클래스를 테스트합니다. 특정 클래스에서 메서드를 호출할 수 있는지 확인합니다.
(Ruby 어휘에서 메시지는 메서드로 알려져 있습니다.)
배송 클래스는 다음과 같습니다.
class Shipment
def prepare_for_delivery
@message = 'Shipment is prepared for delivery'
end
def tracking_code(code)
@tracking_code = code
end
end
react_to?를 사용하세요. prepare_for_delivery 메소드가 존재하는지 확인하는 메소드:
s = Shipment.new
s.respond_to?(:prepare_for_delivery)
==> true
이 메시지가 있는 경우 다른 개체에 메시지를 보내는 보다 완전한 예입니다.
s = Shipment.new
if s.respond_to?(:cancel_shipping)
s.cancel_shipping
else
puts "Oh no ! Shipment cannot be cancel."
end
모든 수업에 사용할 수 있습니다.
'hello'.respond_to?(:count)
==> true
'world'.respond_to?(:include)
==> false
잡았어?
글쎄, 이 기사의 끝을 염두에 두십시오.
send() 메서드
send() 메서드를 사용하여 클래스의 모든 메서드를 호출할 수 있습니다.
s = Shipment.new
if s.respond_to?(:tracking_code)
s.send(:tracking_code, '123ABC') # or s.send('cancel_shipping', '123ABC')
else
puts "Tracking code is not available."
end
(send()의 첫 번째 파라미터로 메시지를 보낸다.)
"우리 방법을 직접 호출하지 않는 이유는 무엇입니까?"라는 말을 듣고 있습니다.
예, 가능하며 이 예는 우리가 사용하는 방법에 대한 실제 예가 아님을 알고 있습니다.
계속합시다.
define_method() 메서드
이제 논리를 알았으므로 설명하기 전에 이 메서드의 동작을 찾을 수도 있습니다.
그것은… 방법을 정의합니다 ? 잘했어요 !
class Shipment
define_method :cancel do |reason|
@cancelled = true
puts reason
end
end
취소된 인스턴스 변수를 true로 설정하고 이유를 인쇄하여 Shipment 클래스에 대한 새 메서드를 정의했습니다.
당신의 마음을 사로잡을 마지막 예를 들어보세요.
한 가지 예의 메타프로그래밍
Ruby 메타프로그래밍의 기본 사항을 알고 있습니다. 마지막 예제를 살펴보겠습니다.
메타 프로그래밍으로의 바다 여행을 떠나 항해를 시작합시다!
# We create a container class. We only store the product's name at instantiation
class Container
attr :product_name
def initialize(name)
@product_name = name
end
end
# Apples ! Oranges ! All of theses fruits are contained in FruitContainer extending Container
# For simplification we only have one scanner
class FruitContainer < Container
def apples_scanner
puts "Scanning apples..."
end
end
# Potatoes ! Broccoli ! All of vegetables are contained in VegetableContainer extending Container
# For simplification we only have one scanner
class VegetableContainer < Container
def potatoes_scanner
puts "Scanning potatoes..."
end
end
# The Cargo containing all the containers
class Cargo
# The constructor accepting multiple parameters
def initialize(*containers)
containers.each do |container|
# self.class.send is used to define singleton methods for our class
# we could also use define_singleton_method
self.class.send(:define_method, "inspect_#{container.product_name}") do
scanner_name = "#{container.product_name}_scanner"
if container.respond_to?(scanner_name)
container.send(scanner_name)
else
puts "No scanner found."
end
end
end
end
end
potatoes_container = VegetableContainer.new "potatoes"
apples_container = FruitContainer.new "apples"
cargo = Cargo.new(potatoes_container, apples_container)
cargo.inspect_apples
cargo.inspect_potatoes
우리는 내가 설명한 모든 방법을 사용했습니다. 각 컨테이너 클래스에 대해 제품 이름인 스캐너를 기반으로 메서드(존재하는 경우)를 호출하는 새 메서드를 정의합니다.
출력:
Scanning apples...
Scanning potatoes...
이제 메타프로그래밍이 무엇이며 어떻게 작동하는지 알게 되었습니다. 잘했어요.
메타 프로그래밍의 첫 번째 사용 사례 중 하나는 자체 DSL(도메인 특정 언어)을 만드는 것입니다.
DevOps 사용자를 위한 Ruby DSL(Chef 및 Puppet 기반의 잘 알려진 도구가 있습니다.
이것이 Ruby를 아름답게 만드는 것입니다.
이 주제에 대한 책을 제공할 수 없기 때문에 귀하의 모든 질문과 피드백에 답해 드립니다.
Reference
이 문제에 관하여(루비를 아름답게 만드는 것: 메타프로그래밍), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/alexlion/what-makes-ruby-beautiful-metaprogramming-536a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Shipment
def prepare_for_delivery
@message = 'Shipment is prepared for delivery'
end
def tracking_code(code)
@tracking_code = code
end
end
s = Shipment.new
s.respond_to?(:prepare_for_delivery)
==> true
s = Shipment.new
if s.respond_to?(:cancel_shipping)
s.cancel_shipping
else
puts "Oh no ! Shipment cannot be cancel."
end
'hello'.respond_to?(:count)
==> true
'world'.respond_to?(:include)
==> false
send() 메서드를 사용하여 클래스의 모든 메서드를 호출할 수 있습니다.
s = Shipment.new
if s.respond_to?(:tracking_code)
s.send(:tracking_code, '123ABC') # or s.send('cancel_shipping', '123ABC')
else
puts "Tracking code is not available."
end
(send()의 첫 번째 파라미터로 메시지를 보낸다.)
"우리 방법을 직접 호출하지 않는 이유는 무엇입니까?"라는 말을 듣고 있습니다.
예, 가능하며 이 예는 우리가 사용하는 방법에 대한 실제 예가 아님을 알고 있습니다.
계속합시다.
define_method() 메서드
이제 논리를 알았으므로 설명하기 전에 이 메서드의 동작을 찾을 수도 있습니다.
그것은… 방법을 정의합니다 ? 잘했어요 !
class Shipment
define_method :cancel do |reason|
@cancelled = true
puts reason
end
end
취소된 인스턴스 변수를 true로 설정하고 이유를 인쇄하여 Shipment 클래스에 대한 새 메서드를 정의했습니다.
당신의 마음을 사로잡을 마지막 예를 들어보세요.
한 가지 예의 메타프로그래밍
Ruby 메타프로그래밍의 기본 사항을 알고 있습니다. 마지막 예제를 살펴보겠습니다.
메타 프로그래밍으로의 바다 여행을 떠나 항해를 시작합시다!
# We create a container class. We only store the product's name at instantiation
class Container
attr :product_name
def initialize(name)
@product_name = name
end
end
# Apples ! Oranges ! All of theses fruits are contained in FruitContainer extending Container
# For simplification we only have one scanner
class FruitContainer < Container
def apples_scanner
puts "Scanning apples..."
end
end
# Potatoes ! Broccoli ! All of vegetables are contained in VegetableContainer extending Container
# For simplification we only have one scanner
class VegetableContainer < Container
def potatoes_scanner
puts "Scanning potatoes..."
end
end
# The Cargo containing all the containers
class Cargo
# The constructor accepting multiple parameters
def initialize(*containers)
containers.each do |container|
# self.class.send is used to define singleton methods for our class
# we could also use define_singleton_method
self.class.send(:define_method, "inspect_#{container.product_name}") do
scanner_name = "#{container.product_name}_scanner"
if container.respond_to?(scanner_name)
container.send(scanner_name)
else
puts "No scanner found."
end
end
end
end
end
potatoes_container = VegetableContainer.new "potatoes"
apples_container = FruitContainer.new "apples"
cargo = Cargo.new(potatoes_container, apples_container)
cargo.inspect_apples
cargo.inspect_potatoes
우리는 내가 설명한 모든 방법을 사용했습니다. 각 컨테이너 클래스에 대해 제품 이름인 스캐너를 기반으로 메서드(존재하는 경우)를 호출하는 새 메서드를 정의합니다.
출력:
Scanning apples...
Scanning potatoes...
이제 메타프로그래밍이 무엇이며 어떻게 작동하는지 알게 되었습니다. 잘했어요.
메타 프로그래밍의 첫 번째 사용 사례 중 하나는 자체 DSL(도메인 특정 언어)을 만드는 것입니다.
DevOps 사용자를 위한 Ruby DSL(Chef 및 Puppet 기반의 잘 알려진 도구가 있습니다.
이것이 Ruby를 아름답게 만드는 것입니다.
이 주제에 대한 책을 제공할 수 없기 때문에 귀하의 모든 질문과 피드백에 답해 드립니다.
Reference
이 문제에 관하여(루비를 아름답게 만드는 것: 메타프로그래밍), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/alexlion/what-makes-ruby-beautiful-metaprogramming-536a
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Shipment
define_method :cancel do |reason|
@cancelled = true
puts reason
end
end
Ruby 메타프로그래밍의 기본 사항을 알고 있습니다. 마지막 예제를 살펴보겠습니다.
메타 프로그래밍으로의 바다 여행을 떠나 항해를 시작합시다!
# We create a container class. We only store the product's name at instantiation
class Container
attr :product_name
def initialize(name)
@product_name = name
end
end
# Apples ! Oranges ! All of theses fruits are contained in FruitContainer extending Container
# For simplification we only have one scanner
class FruitContainer < Container
def apples_scanner
puts "Scanning apples..."
end
end
# Potatoes ! Broccoli ! All of vegetables are contained in VegetableContainer extending Container
# For simplification we only have one scanner
class VegetableContainer < Container
def potatoes_scanner
puts "Scanning potatoes..."
end
end
# The Cargo containing all the containers
class Cargo
# The constructor accepting multiple parameters
def initialize(*containers)
containers.each do |container|
# self.class.send is used to define singleton methods for our class
# we could also use define_singleton_method
self.class.send(:define_method, "inspect_#{container.product_name}") do
scanner_name = "#{container.product_name}_scanner"
if container.respond_to?(scanner_name)
container.send(scanner_name)
else
puts "No scanner found."
end
end
end
end
end
potatoes_container = VegetableContainer.new "potatoes"
apples_container = FruitContainer.new "apples"
cargo = Cargo.new(potatoes_container, apples_container)
cargo.inspect_apples
cargo.inspect_potatoes
우리는 내가 설명한 모든 방법을 사용했습니다. 각 컨테이너 클래스에 대해 제품 이름인 스캐너를 기반으로 메서드(존재하는 경우)를 호출하는 새 메서드를 정의합니다.
출력:
Scanning apples...
Scanning potatoes...
이제 메타프로그래밍이 무엇이며 어떻게 작동하는지 알게 되었습니다. 잘했어요.
메타 프로그래밍의 첫 번째 사용 사례 중 하나는 자체 DSL(도메인 특정 언어)을 만드는 것입니다.
DevOps 사용자를 위한 Ruby DSL(Chef 및 Puppet 기반의 잘 알려진 도구가 있습니다.
이것이 Ruby를 아름답게 만드는 것입니다.
이 주제에 대한 책을 제공할 수 없기 때문에 귀하의 모든 질문과 피드백에 답해 드립니다.
Reference
이 문제에 관하여(루비를 아름답게 만드는 것: 메타프로그래밍), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/alexlion/what-makes-ruby-beautiful-metaprogramming-536a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)