[ruby] 루비 : 인스턴스에서 클래스 메소드 호출

Ruby에서 해당 클래스의 인스턴스 중 하나에서 클래스 메소드를 어떻게 호출합니까? 내가 가지고 있다고

class Truck
  def self.default_make
    # Class method.
    "mac"
  end

  def initialize
    # Instance method.
    Truck.default_make  # gets the default via the class's method.
    # But: I wish to avoid mentioning Truck. Seems I'm repeating myself.
  end
end

라인 Truck.default_make은 기본값을 검색합니다. 그러나 언급하지 않고 이것을 말하는 방법이 Truck있습니까? 있어야 할 것 같습니다.



답변

인스턴스 메서드 내에서 클래스의 리터럴 이름을 참조하는 대신을 호출하면 self.class.whatever됩니다.

class Foo
    def self.some_class_method
        puts self
    end

    def some_instance_method
        self.class.some_class_method
    end
end

print "Class method: "
Foo.some_class_method

print "Instance method: "
Foo.new.some_instance_method

출력 :

수업 방법 : 푸
인스턴스 방법 : Foo


답변

사용 self.class.blahClassName.blah상속 과 관련하여 사용하는 것과 다릅니다 .

class Truck
  def self.default_make
    "mac"
  end

  def make1
    self.class.default_make
  end

  def make2
    Truck.default_make
  end
end


class BigTruck < Truck
  def self.default_make
    "bigmac"
  end
end

ruby-1.9.3-p0 :021 > b=BigTruck.new
 => #<BigTruck:0x0000000307f348> 
ruby-1.9.3-p0 :022 > b.make1
 => "bigmac"
ruby-1.9.3-p0 :023 > b.make2
 => "mac" 


답변

인스턴스 메소드 내부의 클래스 메소드에 액세스하려면 다음을 수행하십시오.

self.class.default_make

문제에 대한 대체 솔루션은 다음과 같습니다.

class Truck

  attr_accessor :make, :year

  def self.default_make
    "Toyota"
  end

  def make
    @make || self.class.default_make
  end

  def initialize(make=nil, year=nil)
    self.year, self.make = year, make
  end
end

이제 우리 수업을 사용하자 :

t = Truck.new("Honda", 2000)
t.make
# => "Honda"
t.year
# => "2000"

t = Truck.new
t.make
# => "Toyota"
t.year
# => nil


답변

delegate 메소드에 액세스 할 수있는 경우 다음을 수행 할 수 있습니다.

[20] pry(main)> class Foo
[20] pry(main)*   def self.bar
[20] pry(main)*     "foo bar"
[20] pry(main)*   end
[20] pry(main)*   delegate :bar, to: 'self.class'
[20] pry(main)* end
=> [:bar]
[21] pry(main)> Foo.new.bar
=> "foo bar"
[22] pry(main)> Foo.bar
=> "foo bar"

또는 클래스 또는 인스턴스에 위임하려는 메소드가 두 개 이상인 경우 더 깨끗할 수 있습니다.

[1] pry(main)> class Foo
[1] pry(main)*   module AvailableToClassAndInstance
[1] pry(main)*     def bar
[1] pry(main)*       "foo bar"
[1] pry(main)*     end
[1] pry(main)*   end
[1] pry(main)*   include AvailableToClassAndInstance
[1] pry(main)*   extend AvailableToClassAndInstance
[1] pry(main)* end
=> Foo
[2] pry(main)> Foo.new.bar
=> "foo bar"
[3] pry(main)> Foo.bar
=> "foo bar"

주의 사항 :

delegate이상한 이름 충돌 문제가 발생하기 때문에 상태를 클래스 및 인스턴스로 변경하지 않는 모든 것을 무작위로하지 마십시오 . 이 작업은 드물게 수행하고 다른 사항을 확인한 후에 만 ​​처리하십시오.


답변

self.class.default_make


답변

당신은 올바른 방법으로하고 있습니다. 클래스 메소드 (C ++ 또는 Java의 ‘정적’메소드와 유사)는 인스턴스의 일부가 아니므로 직접 참조해야합니다.

참고로, 귀하의 예에서 ‘default_make’를 일반적인 방법으로 만드는 것이 더 좋습니다.

#!/usr/bin/ruby

class Truck
    def default_make
        # Class method.
        "mac"
    end

    def initialize
        # Instance method.
        puts default_make  # gets the default via the class's method.
    end
end

myTruck = Truck.new()

클래스 메소드는 클래스를 사용하는 유틸리티 유형 함수에 더 유용합니다. 예를 들면 다음과 같습니다.

#!/usr/bin/ruby

class Truck
    attr_accessor :make

    def default_make
        # Class method.
        "mac"
    end

    def self.buildTrucks(make, count)
        truckArray = []

        (1..count).each do
            truckArray << Truck.new(make)
        end

        return truckArray
    end

    def initialize(make = nil)
        if( make == nil )
            @make = default_make()
        else
            @make = make
        end
    end
end

myTrucks = Truck.buildTrucks("Yotota", 4)

myTrucks.each do |truck|
    puts truck.make
end


답변

하나 더:

class Truck
  def self.default_make
    "mac"
  end

  attr_reader :make

  private define_method :default_make, &method(:default_make)

  def initialize(make = default_make)
    @make = make
  end
end

puts Truck.new.make # => mac