루비 개념 - 단례류

22630 단어 rubybasicssingleton
표지 이미지 신용: Samier SaeedSitePoint.
너는 무엇이 독신계급이라고 생각해 본 적이 있니?당신은 일찍이 다른 사람과 채팅을 하거나 블로그 게시물을 읽은 적이 있습니까? 그러나'외동자녀 과정'이나'외동자녀 방법'이 사용되었습니다. 당신은 미소를 지으며 고개를 끄덕이고 나중에 다시 조사할 수 있도록 다음 메모를 적었을 뿐입니까?지금이 니 때야.지금이 니 때야.나는 더욱 직관적인 언어로 이 개념을 해석하고 너희들에게 그것이 얼마나 편리한지 보여주고 싶다.
방주: 많은 정보는 The Well-Grounded Rubyist의 읽기David A. Black에서 나온다.이 책은 대량의 정보를 가지고 있는데, 현재 내가 가장 좋아하는 루비 서적 중의 하나이다.
방주 #2: 적어도 아래로 끝까지 굴러서 한 개의 치즈와 건강에 기반한 적극성을 얻는다.😁

코드


만약 당신이 루비를 많이 썼다면, 당신은 이미 자신도 모르게 이런'단례류'를 사용했습니다!우선, 나는 당신에게 당신이 이미 작성한 코드를 보여 드리겠습니다. 이렇게 하면 상하문이 좀 생길 것입니다.
class Config
  def self.from_file(filename)
    Config.new(YAML.load_file(filename))
  end
end

dev_config = Config.from_file("config.dev.yaml")
# => Config object with dev settings
이러한 상황을 본 적이 있을 수 있습니다.
module Geometry
  class << self
    def rect_area(length, width)
      length * width
    end
  end
end

Geometry.rect_area(4, 5)
# => 20
지금까지 당신은 이것들을'클래스 방법'이라고 불렀을 수 있습니다너는 기본적으로 옳다.그런데 왜 효과가 있을까요?여기서 무슨 일이 일어났습니까?

개성화


이것은 루비를 이렇게 훌륭하게 하는 핵심 개념이다.하나의 대상은 같은 종류의 대상이라도 서로 다르기 때문에 서로 다른 방법을 정의할 수 있다.이 예에서 나는 파렴치하게 우리의 애완동물을 사용하여 도울 것이다.
class Pet
  def smolder
    "Generic cute pet smolder"
  end
end

succulent = Pet.new
momo = Pet.new
willy = Pet.new

def momo.smolder
  "sassy cat smolder"
end

def willy.smolder
  "well-meaning dingus smolder"
end
현재, 우리가 smolder 에서 호출되었을 때, 우리는 변하지 않았고, 일은 계획대로 진행되었다.
succulent.smolder
# => Generic cute pet smolder"

그러나 우리가 succulent 또는 smolder 에서 willy 를 호출할 때 다른 일이 발생한다!
momo.smolder
# => "sassy cat smolder"

willy.smolder
# => "well-meaning dingus smolder"

그럼, 이것은 어떻게 일합니까?우리는 모든 애완동물을 위해 새롭게 정의했습니까momo?저 좀 도와주세요. 아래의 출력을 보세요.
succulent.singleton_methods
# => []
momo.singleton_methods
# => [:smolder]
willy.singleton_methods
# => [:smolder]
이게 맞습니다!너는 단례적인 방법을 사용하고 있다!지금, 나는 우리가 솔로 계급이 무엇인지 토론할 준비가 되어 있다고 생각한다.

외동 자녀 반은 무엇입니까?


우선, 더 일반적인 프로그래밍, 루비에 그다지 특정되지 않은 문제: 무엇이 단례입니까?서로 다른 상황에 대해 다양한 정의가 있을 수 있지만 그 핵심은 단지 그 중의 하나일 뿐이다.이것은 동종 제품 중 유일한 제품이다.
루비의 컨텍스트에서 이것은 무엇을 의미합니까?이것이 바로 루비의 클래스에서 대상을 실례화할 때, 루비의 클래스가 주는 방법을 알고 있다.그것은 또 어떻게 모든 조상을 그의 계급으로 분류하는지 안다.이것이 바로 상속이 유효한 이유다.

"Oh, my class doesn't have that method? Let's check its parent class. And that class's parent class. Etc."


루비의 가장 멋진 점은 조상 사슬이 디자인에 있어서 매우 명확하다는 것이다.대상이 조상을 검색할 때 특정한 규칙이 있기 때문에 어떤 방법을 사용할지 의심할 여지가 없다.
그것의 클래스를 아는 것을 제외하고, 모든 대상은 그것이 알고 있는 단일 클래스로 만든다.모든 단일 클래스는'ghost 클래스'이거나 더 간단하게 말하면 이 특정한 대상만을 위한 모든 방법을 저장하는 패키지입니다.이것 괜찮아요?
momo.singleton_class
# => #<Class:#<Pet:0x00007fea40060220>>
계승 차원 구조에서는 대상의 실제 클래스 앞에 보이지 않는다.그러나 대상의 조상을 보면 볼 수 없습니다.
momo.class.ancestors
# => [Pet, Object, Kernel, BasicObject]
하지만 우리가 외동족 자체의 조상 나무를 보면
momo.singleton_class.ancestors
# => [#<Class:#<Pet:0x00007fea40060220>>, Pet, Object, Kernel, BasicObject]
너는 그것이 처음부터 나타나는 것을 볼 수 있다.따라서 smolder 찾기 momo 방법을 찾을 때 먼저 그 단례류에서 찾는다.그곳에 smolder 방법이 있기 때문에, 나무에서 smolder 클래스에 정의된 방법을 더 찾는 것이 아니라, 이 방법을 사용한다.

이것은 유형의 방법과 무슨 관계가 있습니까?


지금은 우리가 독신 계급의 힘을 보기 시작할 때다.각 클래스는 클래스의 대상일 뿐이라는 것을 잊지 마세요Pet.만약 그 말이 너로 하여금 지나치게 통기를 하게 한다면, 걱정하지 마라.설명할게요.
Pet.class
# => Class
Class는 하나의 클래스일 뿐입니다. 이것은 당신이 만든 모든 실례 (클래스) 에 다른 클래스와 같은 방법을 제공합니다.
Class.instance_methods(false)
# => [:new, :allocate, :superclass]
따라서, 실제로, 당신이 클래스에서 직접 호출할 계획을 정의할 때, 당신은 실제적으로 특정한 클래스 대상에 방법을 정의합니다. 즉, 클래스의 단일 클래스에서!
class Pet
  def self.random
    %w{cat dog bird fish banana}.sample
  end
end

Pet.singleton_methods
# => [:random]
그리고... 만약 단일 클래스가 존재한다면, 그것은 주 클래스로부터 계승된 클래스의singleton_클래스의 부류가 될 것이다.예를 들면 도움이 될 것 같습니다.
class Pet
  def self.random
    %w{cat dog bird fish banana}.sample
  end
end

class Reptile < Pet
  def self.types
    %w{lizard snake other}
  end
end

Reptile.singleton_methods
# => [:types, :random]
Reptile.singleton_class.ancestors
# => [#<Class:Reptile>, #<Class:Pet>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
보기Class의 단례 클래스는 Reptile의 단례 클래스로부터 어떻게 계승됩니까? 따라서 Pet 사용할 수 있는'클래스 방법'도 Pet 에 사용할 수 있습니까?

기타 에피소드


나는 지금까지 우리가 거의 모든 중요한 부분을 포괄했다고 생각한다.그러나 저는 멋있고 재미있는 디테일이 있습니다. 제목과 관련이 있습니다. 이해하기 어려운 Reptile 문법, 창설 방법의 다른 방식, 그리고 class << self의 사용입니다.만약 당신이 흥미가 있다면, 계속 읽으세요.

뻗다

Class << self 키워드를 사용하는 데는 실제로 두 가지 방법이 있다. 바로 뒤꿈치 상수(laclass, 또는 뒤꿈치'삽 조작원'과 대상(laclass Gelato이다.당신은 이미 첫 번째 방법을 알고 있습니다. - 이것은 당신이 통상적으로 성명하는 방식입니다!두 번째, 그것은 대상을 직접 열 수 있는 단례류의 문법이다.너는 그것이 본질적으로 우리가 위에서 정의한 방법과 같다고 생각할 수 있다.
내 말은:
# This:
def momo.snug
  "*snug*"
end

# is the same (pretty much) as this:
class << momo
  def snug
    "*snug*"
  end
end
더 많은 기능을 추가하기 위해 일반 클래스를 다시 열 때, 계속 이렇게 합니다.
class Gelato
  attr_reader :solidity

  def initialize
    @solidity = 100
  end

  def melt
    @solidity -= 10
  end
end

# And re-open it to add one more method

class Gelato
  def refreeze
    @solidity = 100
  end
end

dessert = Gelato.new
5.times { dessert.melt }
dessert.solidity
# => 50
dessert.refreeze
# => 100
문법class << momo은 대상을 다시 여는 단례류의 다른 방식일 뿐이다.이곳의 장점은 한 번에 상수와 여러 가지 방법을 정의할 수 있다는 것이다. 한 번에 하나를 정의하는 것이 아니라.
# Instead of:
def momo.pounce
  "pounce!"
end

def momo.hiss
  "HISS"
end

def momo.lives
  9
end

# We can do
class << momo
  def pounce
    "pounce!"
  end

  def hiss
    "HISS"
  end

  def lives
    9
  end
end

momo.singleton_methods
# => [:pounce, :hiss, :lives, :smolder]
여러 클래스 방법을 한 클래스에 추가하여 다음 내용을 볼 때 흔히 볼 수 있는 패턴입니다.
class Pet
  class << self
    def random
      %w{cat dog bird fish banana}.sample
    end
  end
end

# Which, since "self" is inside of the class
# declaration, means that 'self == Pet', so you could
# also do this:

class Pet
  class << Pet
    def random
      # ...
    end
  end
end
이런 패턴을 보았을 수도 있지만, 그것이 무엇인지 모르거나, 종류를 추가한 방법을 알고 있을 수도 있지만, 왜 그런지 모르겠다.이제 알았어!이 모든 것은 독신반에게 감사해야 한다!

클래스<<개체;종료 및 범주 <self vs defself.방법


몇 가지 다른 방법으로 유형의 방법을 성명한다.
# 1. In global scope
def Pet.random
  %w{cat dog bird fish banana}.sample
end

# 2. Inside the class definition, using 'self'
class Pet
  def self.random
    %w{cat dog bird fish banana}.sample
  end
end

# 3. Inside the class definition, using the shovel
class Pet
  class << self
    def random
      %w{cat dog bird fish banana}.sample
    end
  end
end

# 4. Outside the class definition, using the shovel
class << Pet
  def random
    %w{cat dog bird fish banana}.sample
  end
end
그럼 뭐가 달라요?너는 언제 하나 또는 다른 것을 쓰니?
좋은 소식은 그것들이 기본적으로 모두 같다는 것이다.코드 라이브러리 스타일과 일치하는 모든 것을 사용할 수 있습니다.유일한 차이점은 #3과 상수와 범위를 어떻게 처리하는가이다.
MAX_PETS = 3

def Pet.outer_max_pets
  MAX_PETS
end

class Pet
  MAX_PETS = 1000

  class << self
    def inner_max_pets
      MAX_PETS
    end
  end
end

Pet.outer_max_pets
# => 3
Pet.inner_max_pets
# => 1000
보기def Pet.method 함수는 inner_max_pets 클래스 내의 작용역과 그 상수에 접근할 수 있습니까?이것은 정말 유일한 차이다.당신이 가장 좋아하는 문법을 안심하고 계속 사용하세요.

Extend를 사용하여 내장 클래스를 안전하게 수정합니다.


언젠가 블로그 글을 읽었거나 루비 클래스를 다시 열 수 있다는 경고가 나왔으면 합니다.다음 일을 하는 것은 매우 조심해야 한다.
class String
  def verbify
    self + "ify"
  end
end

"banana".verbify
# => "bananaify"
위험은 의외의 덮어쓰기 내장 방법, 방법이 같은 프로젝트의 다른 라이브러리와 충돌하는 것, 그리고 일반적으로 일을 기대에 부합되지 않게 하는 것을 포함한다.Pet 키워드는 이 모든 것을 실현하는 데 도움을 줄 수 있습니다!

확장이란 무엇입니까?


키워드 extend 는 다른 클래스/모듈에서 클래스/모듈로 기능을 불러올 수 있도록 하기 때문에 extend 와 매우 비슷합니다.그러나 다른 점은 include 이러한 방법을 목표 대상의 단례류에 두는 것이다.
module Wigglable
  def wiggle
    "*shimmy*"
  end
end

willy.extend(Wiggleable)
willy.singleton_methods
# => [:wiggle, :smolder]
따라서 클래스 정의에서 extend 가 아닌 extend 을 사용한다면 이러한 방법은 클래스의 단일 클래스에 클래스 방법으로 추가하는 것이지 실례적인 방법으로 클래스 자체에 추가하는 것이 아니다.
module Hissy
  def hiss
    "HISS"
  end
end

class Reptile
  extend Hissy
end

snek = Reptile.new
snek.hiss
# => Error!  Undefined method hiss for 'snek'
Reptile.hiss
# => "HISS"

이것은 우리에게 무슨 도움이 됩니까?


만약 우리가 정말 우리가 사용하는 문자열에 include 방법을 사용해야 한다고 가정해 보세요.verbify 의 하위 클래스를 만들고 사용할 수 있지만, 다른 옵션은 단일 문자열을 확장하는 것입니다!
module Verby
  def verbify
    self + "ify"
  end
end

noun = "pup"
noun.extend(Verby)
noun.verbify
# => "pupify"

치즈 팩


그러니 한 가지는 듣기 무서운 화제일 뿐만 아니라 매우 복잡한 루비 주제도 아니라는 것을 명심하세요.너는 진정한 외동딸이다. 그래, 너는 한 사람이지만, 너처럼 다른 사람은 없다.너는 자신의 직업과 일하는 방법이 있는데, 이것은 매우 가치가 있다.지금 우리는 방금 당신을 위해 더 많은 기능을 추가했습니다.
class << you
  def use_singletons_for_fun_and_profit
    # ...
  end
end

좋은 웹페이지 즐겨찾기