Ruby继承和重写类方法

Ruby继承和重写类方法,ruby,inheritance,class-method,Ruby,Inheritance,Class Method,我设置了两个类,如下所示 class Parent def self.inherited(child) child.custom_class_method end def self.custom_class_method raise "You haven't implemented me yet!" end end class Child < Parent def self.custom_class_method "hello world

我设置了两个类,如下所示

class Parent

  def self.inherited(child)
    child.custom_class_method
  end

  def self.custom_class_method
    raise "You haven't implemented me yet!"
  end
end

class Child < Parent

  def self.custom_class_method
    "hello world"
  end
end
类父类
def self.inherited(子项)
child.custom\u class\u方法
结束
def self.custom_class_方法
raise“你还没有实现我!”
结束
结束
类子<父
def self.custom_class_方法
“你好,世界”
结束
结束
似乎在计算继承
时,它会调用
self.inherited
,这反过来会引发父
self.custom\u class\u方法的
版本,而不是子
。这是一个问题,因为我没有得到预期的
“hello world”
,而是收到一个错误,提示说
“您还没有实现我!”


在父级
自继承的
完成评估之前,
子级
自自定义类
方法是否不会得到评估?如果是这样的话,也许有一个工作围绕这一点?我是否应该不在父类上进行
raise
检查

我认为这应该澄清:

class Parent
  def self.inherited(child)
    puts "Inherited"
  end
end

class Child < Parent
  puts "Starting to define methods"
  def self.stuff; end
end
类父类
def self.inherited(子项)
“继承的”
结束
结束
类子<父
放置“开始定义方法”
定义自我的东西;结束
结束
输出表明,
.inherited
在您打开新类时被调用,而不是在您关闭它时被调用。因此,正如您所猜测的,
Child.custom\u class\u方法
在您试图调用它时并不存在-所有的
。继承的
所看到的都是一张白板


(至于如何绕过它……不幸的是,我不能不深入了解您正在尝试做什么。)

模板模式/延迟初始化可能有助于解决您的问题。代码假定子类之间的不同之处在于数据库连接信息,可能只是表名,也可能是完全不同的数据库。父类拥有创建和维护连接的所有代码,子类只负责提供不同的内容

class Parent
  def connection
    @connection ||= make_connection
  end

  def make_connection
    puts "code for making connection to database #{database_connection_info}"
    return :the_connection
  end

  def database_connection_info
    raise "subclass responsibility"
  end
end

class Child1 < Parent
  def database_connection_info
    {host: '1'}
  end
end

class Child2 < Parent
  def database_connection_info
    {host: '2'}
  end
end

child1 = Child1.new
child1.connection  # => makes the connection with host: 1
child1.connection  # => uses existing connection

Child2.new.connection  # => makes connection with host: 2
类父类
def连接
@连接| |=建立连接
结束
def make_连接
放置“连接到数据库#{database_connection_info}的代码”
return:the_连接
结束
def数据库连接信息
提出“子类责任”
结束
结束
儿童1级<父母
def数据库连接信息
{主机:'1'}
结束
结束
儿童2级<父母
def数据库连接信息
{主机:'2'}
结束
结束
child1=child1.new
child1.connection#=>与主机建立连接:1
child1.connection#=>使用现有连接
Child2.new.connection#=>与主机建立连接:2

这似乎很奇怪。获取父级的
自定义\u类\u方法的唯一方法应该是调用
super
。否则,只需调用
Child.custom_class_方法
就会得到“hello world”输出。你能提供更深入的日志记录吗?嗯,我同意应该这样做!但似乎我可以通过简单地将代码块复制粘贴到
irb
控制台来复制这一点。正是因为这个原因,在评估
子类时它出错了。啊,聪明,我没有想过这样调试它!那么,在这里定义抽象方法的最佳方式是什么呢?我是否只是避免引发错误(老实说,这让我很不舒服)。本质上,我试图创建一个父类,该类能够在
self.inherited
块中执行代码,该块在不同的子类中会略有不同。但是,为了确保不会出现错误,我想强制要求每个继承的子级定义
自定义\u方法
(这就是为什么我要提升父类)。不要问“如何在继承时执行子级代码”,因为你不能。这似乎是一个XY问题。为什么要在继承时执行子代码
.inherited
用于通知新子女的家长,而不是在子女上运行代码。孩子们可以在孩子们身上运行代码(请参见我的
put
)。啊,我明白了。似乎我的思维过程本质上并没有遵循继承的设计原则(我认为这很好)。我希望做的是将各种类正在做的逻辑(它们每个都在类级别建立到自己的定制数据库的连接)抽象到父类中。一旦继承,父母会询问孩子他们想要连接到哪个数据库,并为他们这样做。这将有希望抽象并保持这个逻辑干涸,而不是在每个模型中重复。是的,很抱歉含糊不清,但你的建议实际上是正确的。非常感谢。因此,在每个子系统中,我将调用
数据库管理器。连接到(自定义数据库)
。再次感谢!太棒了,谢谢!作为一个设计问题,您认为这比将其抽象为一个维护此连接逻辑并调用
DatabaseManager的
DatabaseManager模型好/坏吗?在每个类中创建连接而不是继承它?这是一个很好的问题。授权与继承是一个由来已久的问题。Rails通过继承实现持久性(技术上可以包括模块,但通常通过继承实现)。许多人认为持久性不应该是类的责任,而应该转向另一个方向,比如数据映射器模式()。即使您属于persistence-is-a-responsibility阵营,您可能仍然希望在类之外抽象数据库行为——可能是连接池。这方面有很好的库,比如sequel gem。我不赞同
DatabaseManager
的想法,所以这是另一个很好的建议。正如我所说,我的回答肯定是含糊不清的,因为你们比我更了解你们的项目。我想说的要点是,您不能在继承上执行此操作。您可以使用外部管理器或继承的m