从Ruby中该类包含的模块调用类方法

时间:2022-11-12 23:22:19

In the code below, I would like to call the class method done of the class that includes the module from inside self.hello

在下面的代码中,我想调用包含self.hello中的模块的类的类方法

Explanation:

A::bonjour will call Mod::hello so will B::ciao

A :: bonjour将调用Mod :: hello,因此B :: ciao将会调用

I would like to be able to detect the "calling class" (A or B) in Mod::hello in order to be able to call the A::done or B::done

我希望能够在Mod :: hello中检测“调用类”(A或B),以便能够调用A :: done或B :: done

module Mod
 def self.hello
  puts "saying hello..."
 end
end

class A
 include Mod

 def self.bonjour
  Mod::hello 
 end

 def self.done
  puts "fini"
 end
end

class B
 include Mod

 def self.ciao
  Mod::hello
 end

 def self.done
  puts "finitto"
 end
end

1 个解决方案

#1


3  

While (perhaps) not as clean as Niklas' answer, it's still easily doable, and IMO cleaner than the usage pattern shown in the OP which relies on knowing which module is mixed in.

虽然(也许)不像Niklas的回答那么干净,但它仍然很容易实现,而且IMO比OP中显示的使用模式更清洁,它依赖于知道混合了哪个模块。

(I prefer not having to pass an argument to mixin methods like this when other means exist.)

(当存在其他方法时,我更喜欢不必将参数传递给mixin方法。)

The output:

pry(main)> A::bonjour
saying hello...
fini
pry(main)> B::ciao
saying hello...
finitto

The guts:

module Mod
  module ClassMethods
    def hello
      puts "saying hello..."
      done
    end
  end

  def self.included(clazz)
    clazz.extend ClassMethods
  end
end

The modified class declarations, removing the explicit module reference:

修改后的类声明,删除显式模块引用:

class A
  include Mod

  def self.bonjour
    hello
  end

  def self.done
    puts "fini"
  end
end

class B
  include Mod

  def self.ciao
    hello
  end

  def self.done
    puts "finitto"
  end
end

You may also supply a default implementation of done:

您还可以提供已完成的默认实现:

module Mod
  module ModMethods
    def hello
      puts "saying hello..."
      done
    end

    def done
      throw "Missing implementation of 'done'"
    end
  end

  def self.included(clazz)
    clazz.extend ModMethods
  end
end

As a comment to this post points out, if the snippet in the OP is a faithful representation of the actual usecase, you might as well use extend (instead of include), leaving everything cleaner:

正如对这篇文章的评论所指出的,如果OP中的片段是对实际用例的忠实表示,那么你也可以使用extend(而不是include),让一切都更清晰:

module Mod
  def hello
    puts "saying hello..."
    done
  end

  def done
    raise NotImplementError("Missing implementation of 'done'")
  end
end

And the classes using extend:

使用扩展的类:

class A
  extend Mod

  def self.bonjour
    hello
  end

  def self.done
    puts "fini"
  end
end

#1


3  

While (perhaps) not as clean as Niklas' answer, it's still easily doable, and IMO cleaner than the usage pattern shown in the OP which relies on knowing which module is mixed in.

虽然(也许)不像Niklas的回答那么干净,但它仍然很容易实现,而且IMO比OP中显示的使用模式更清洁,它依赖于知道混合了哪个模块。

(I prefer not having to pass an argument to mixin methods like this when other means exist.)

(当存在其他方法时,我更喜欢不必将参数传递给mixin方法。)

The output:

pry(main)> A::bonjour
saying hello...
fini
pry(main)> B::ciao
saying hello...
finitto

The guts:

module Mod
  module ClassMethods
    def hello
      puts "saying hello..."
      done
    end
  end

  def self.included(clazz)
    clazz.extend ClassMethods
  end
end

The modified class declarations, removing the explicit module reference:

修改后的类声明,删除显式模块引用:

class A
  include Mod

  def self.bonjour
    hello
  end

  def self.done
    puts "fini"
  end
end

class B
  include Mod

  def self.ciao
    hello
  end

  def self.done
    puts "finitto"
  end
end

You may also supply a default implementation of done:

您还可以提供已完成的默认实现:

module Mod
  module ModMethods
    def hello
      puts "saying hello..."
      done
    end

    def done
      throw "Missing implementation of 'done'"
    end
  end

  def self.included(clazz)
    clazz.extend ModMethods
  end
end

As a comment to this post points out, if the snippet in the OP is a faithful representation of the actual usecase, you might as well use extend (instead of include), leaving everything cleaner:

正如对这篇文章的评论所指出的,如果OP中的片段是对实际用例的忠实表示,那么你也可以使用extend(而不是include),让一切都更清晰:

module Mod
  def hello
    puts "saying hello..."
    done
  end

  def done
    raise NotImplementError("Missing implementation of 'done'")
  end
end

And the classes using extend:

使用扩展的类:

class A
  extend Mod

  def self.bonjour
    hello
  end

  def self.done
    puts "fini"
  end
end