другой способ создания объектно-ориентированных методов в ruby - PullRequest
0 голосов
/ 11 февраля 2019

Мне известен только один способ создания специфичных для экземпляра методов в ruby, т.е.

 class Test;end
 obj1 = Test.new
 class << obj1
   def greet
     p 'Welcome'
   end
 end
 obj1.greet #    "Welcome"
 obj2 = Test.new
 obj2.greet # through error as,
 Traceback (most recent call last):
 NoMethodError (undefined method `greet' for #Test:0x0000564fb35acef0>)

или

 class Test;end
 class << (obj1 = Test.new)
   def greet
     p 'Welcome'
   end
 end
 obj1.greet #    "Welcome"
 obj2 = Test.new
 obj2.greet # through error as,
 Traceback (most recent call last):
 NoMethodError (undefined method `greet' for #Test:0x0000564fb35acef0>)

Здесь у меня есть два вопроса:

  1. Как в реальном мире используются такие специфические для объекта методы?
  2. Какие существуют другие способы создания специфичных для объекта методов в Ruby?

Ответы [ 4 ]

0 голосов
/ 12 февраля 2019

Пример варианта использования: предположим, у вас есть рабочий код, который использует хеш в качестве структуры данных.С течением времени создается впечатление, что класс был бы лучшим выбором, потому что требуется более умное поведение, чем просто хранение данных - например, данные должны быть проверены.Этот проверочный код имеет смысл только в контексте этого конкретного хэша.Вы можете определить метод validate_username в общедоступном пространстве имен или в каком-либо модуле, но, возможно, def the_hash.validate_username;#code;end будет лучшим решением.

0 голосов
/ 11 февраля 2019

Согласно комментарию @mu_is_too_short, есть и другой способ:

class Test; end
obj1 = Test.new

def obj1.pancakes
  p 'Where is pancakes house?'
end

obj1.pancakes # "Where is pancakes house?"
obj2 = Test.new
obj2.pancakes
Traceback (most recent call last) :
NoMethodError
(undefined method `pancakes' for #<Test:0x0000564fb35ca310>)
0 голосов
/ 12 февраля 2019
class Test
end

obj = Test.new

Вот несколько способов создания хэша, отличных от

class << obj
  def greet
    ...
  end
end

и (как уже упоминалось в другом ответе)

def obj.greet
  ...
end

# 1

obj.singleton_class.class_eval do
  def greet1
    'Welcome'
  end
end

obj.greet1 #=> "Welcome"

# 2

obj.singleton_class.class_eval "def greet2
  'Get lost'
end"

obj.greet2 #=> "Get lost" 

Эта форма может быть полезна при динамическом создании одноэлементных методов.

# 3

obj.singleton_class.instance_eval do
  define_method(:greet3) { 'yo' }
end

obj.greet3 #=> "yo"

# 4

obj.singleton_class.
    public_send(:define_method, :greet4) { 'yo-yo' }

obj.greet4 #=> "yo-yo"

# 5

obj.define_singleton_method(:greet5) { 'yo who?' }

obj.greet5 #=> "ho who?"

# 6

module M
  def greet6
    'hi ya'
  end
end

obj.extend M

obj.greet6 #=> "hi ya"

# 7

module M
  def greet7
    'hi you'
  end
end

obj.singleton_class.include M

obj.greet7 #=> "hi you"

obj.methods(false)
  #=> [:greet3, :greet4, :greet1, :greet2, :greet5] 
obj.methods.grep /greet/
  #=> [:greet3, :greet4, :greet1, :greet2, :greet5,
  #    :greet6, :greet7] 

Практическое использование создания синглтонаМетоды очевидны для модулей (включая классы), но требуют мнения относительно других объектов.

0 голосов
/ 11 февраля 2019

Вы определили блок класса как class << obj1 только для объекта obj1, который является специфичным для объекта.Таким образом, метод greet определен только для объекта obj1, а не для других объектов того же класса.

Лучше проверить в следующем шаблоне

class Test
  attr_accessor :name

  def initialize(name)
    self.name = name
  end
end

obj1 = Test.new('test1')

class << obj1
  def greet
    puts self.inspect, self.object_id, self.name
    puts 'Welcome'
  end
end

obj1.greet
obj2 = Test.new
obj2.greet

In выше, obj1 &obj2 оба имеют разные идентификаторы объектов.

1.Как в реальном мире используются такие специфические для объекта методы?

Хорошей практикой является знание различных шаблонов для определения методов.Это полезно, когда вы хотите определить методы динамически или когда вы загружаете классы, но хотите определить методы на основе столбцов таблицы моделей, присутствующих в базе данных. Модуль # define_method является одним из лучших для такого использования, cancancan является одним из гемов, которые динамически определяют вспомогательные методы в инициализаторе.

2.Каковы другие способы создания объектно-ориентированных методов в Ruby?

  1. define_singleton_method
  2. class_eval
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...