ruby中的继承缓存模式

ruby中的继承缓存模式,ruby,oop,inheritance,design-patterns,Ruby,Oop,Inheritance,Design Patterns,假设我有一个父类: class Stat def val raise "method must be implemented by subclass" end end 和一个子类: class MyStat < Stat def val #performs costly calculation and returns value end end 通常,无论是否存在继承,我都使用一个简单的模式: class Parent def val

假设我有一个父类:

class Stat

  def val
    raise "method must be implemented by subclass"
  end

end
和一个子类:

class MyStat < Stat

  def val
    #performs costly calculation and returns value
  end    

end

通常,无论是否存在继承,我都使用一个简单的模式:

class Parent
  def val
    @val ||= calculate_val
  end

  def calculate_value
    fail "Implementation missing"
  end
end

class Child < Parent
  def calculate_val
    # some expensive computation
  end
end

通常,无论是否存在继承,我都使用一个简单的模式:

class Parent
  def val
    @val ||= calculate_val
  end

  def calculate_value
    fail "Implementation missing"
  end
end

class Child < Parent
  def calculate_val
    # some expensive computation
  end
end

如果您希望保持方法名称不变,并且不创建新的方法来放入逻辑,那么可以预先添加模块,而不是使用父/子继承

module MA
  def val
    puts("module's method")
    @_val ||= super
  end
end

class CA
  def val
    puts("class's method")
    1
  end

  prepend MA
end

ca = CA.new
ca.val # will print "module's method" and "class's method". will return 1.
ca.val # will print "module's method". will return 1.

如果您希望保持方法名称不变,并且不创建新的方法来放入逻辑,那么可以预先添加模块,而不是使用父/子继承

module MA
  def val
    puts("module's method")
    @_val ||= super
  end
end

class CA
  def val
    puts("class's method")
    1
  end

  prepend MA
end

ca = CA.new
ca.val # will print "module's method" and "class's method". will return 1.
ca.val # will print "module's method". will return 1.

这真漂亮。似乎
prepend
有几个有用的用法。这非常好,不幸的是我没有完全阐明我的用例,结果证明这对我不起作用。我有一个多层次的完整继承层次结构(StatUnit是父类,Stat和StatSet继承自StatUnit,Stat和StatSet有子类和自己的子类,等等),如果我在我的顶级类中实现了这一点,它对该类的任何子类都不起作用,他的回答是。但请注意,我不鼓励您在Ruby中实现抽象类的Java类型。显然,我假设
Stat
(最顶层的父类)是一个抽象类,它没有在任何地方被实例化。如果是这种情况,那么更像Ruby的方法是将
Stat
转换成一个模块(可能是
StatMethods
),并将其包含在实际实例化的类(或父类)中。这很好。似乎
prepend
有几个有用的用法。这非常好,不幸的是我没有完全阐明我的用例,结果证明这对我不起作用。我有一个多层次的完整继承层次结构(StatUnit是父类,Stat和StatSet继承自StatUnit,Stat和StatSet有子类和自己的子类,等等),如果我在我的顶级类中实现了这一点,它对该类的任何子类都不起作用,他的回答是。但请注意,我不鼓励您在Ruby中实现抽象类的Java类型。显然,我假设
Stat
(最顶层的父类)是一个抽象类,它没有在任何地方被实例化。如果是这种情况,那么更像Ruby的方法是将
Stat
转换成一个模块(可能是
StatMethods
),并将其包含在实际实例化的类(或父类)中,没有标准的方式来声明它们,按照Ruby标准,在
提升中存根是一个非常绝望的举动。通常情况下,您会看到基类实现null大小写,或者做尽可能少的工作,文档清楚地表明您的子类必须实现许多事情。有测试来执行所有的方法是至关重要的,这里不需要依靠编译器来发现错误。指导人们应该做什么。如果他们不听,不要大惊小怪。@tadman谢谢,听到这个很好。我的第一门语言是java,我情不自禁地感到它对我在其他语言中与设计相关的思维产生了有害的影响。ruby的方法是悄悄地失败。我只是忍不住觉得代码应该是自文档化的,因此,如果没有我为此编写的冗长文档,我编写的代码可能就没有意义,这一想法让我感到不安,尽管也许不应该。就像人们学习一种语言时会带着另一种语言的口音一样,编程时也是如此。Java方式和Ruby方式经常不一致,Ruby更随意。因此,此类测试是验证已实施正确行为的唯一方法。抽象基类只是解决问题的一种方法,但也有其他方法可以达到同样的目的。就我个人而言,我喜欢meagar的回答,这是Ruby方式,对您的异常要求有一个小小的让步。抽象基类在Ruby中并不常见,没有标准的方式来声明它们,而按Ruby标准,在
raise
中存根是一个非常绝望的举动。通常情况下,您会看到基类实现null大小写,或者做尽可能少的工作,文档清楚地表明您的子类必须实现许多事情。有测试来执行所有的方法是至关重要的,这里不需要依靠编译器来发现错误。指导人们应该做什么。如果他们不听,不要大惊小怪。@tadman谢谢,听到这个很好。我的第一门语言是java,我情不自禁地感到它对我在其他语言中与设计相关的思维产生了有害的影响。ruby的方法是悄悄地失败。我只是忍不住觉得代码应该是自文档化的,因此,如果没有我为此编写的冗长文档,我编写的代码可能就没有意义,这一想法让我感到不安,尽管也许不应该。就像人们学习一种语言时会带着另一种语言的口音一样,编程时也是如此。Java方式和Ruby方式经常不一致,Ruby更随意。因此,此类测试是验证已实施正确行为的唯一方法。抽象基类只是解决问题的一种方法,但也有其他方法可以达到同样的目的。就我个人而言,我喜欢meagar的回答,这是Ruby方式,对您的异常要求有一点让步。谢谢。实际上,我曾经写过这篇文章,但不幸的是,我也想缓存方法“to_string”的值,我不喜欢“calculate_string”的声音。我可以说“calculate_value”和“build_string”,但是我会用不同的语言来描述相同类型的方法。我想我可能会在任何地方都使用“build_u2;”。谢谢。我曾经写过这篇文章,但是