如何使类仅继承其父级的初始化方法?

时间:2013-06-24 21:16:27

标签: ruby class

我有一个类似于这样开始的课​​程:

class Hedgehogs
  attr_accessor :name, :age, :color, :weight, :fur_quality, :disposition, :sexual_aggression, :has_syphilis # ... etc etc.

具有由方法initialize定义的长属性列表,这些属性因类的每个新实例而异。

但我发现马达加斯加刺猬总是棕色,性侵略性,对梅毒免疫,所以这些属性总是一样的。

我是否应该为了效率而创建一个新类MadagascarHedgehogs,如果是这样,我如何确定新类继承Hedgehogs'属性,仅使用来自initialize的select属性而在类定义中呢?

3 个答案:

答案 0 :(得分:1)

有几种不同的方法可以解决这个问题。我可能会添加一个从initialize调用的钩子方法,并覆盖你的子类。我还建议使用散列而不是initialize的单个参数,特别是因为你有很多变量:

class Hedgehog
  def initialize(attributes = {})
    attributes.each do |key, value|
      instance_variable_set("@#{key}", value)
    end
    set_constant_attributes
  end

  def set_constant_attributes
  end
end

class MadagascarHedgehog
  def set_constant_attributes
    @default1 = 'default value 1'
  end
end

您也可以通过覆盖initialize来执行此操作而不使用钩子方法:

class MadagascarHedgehog
  def initialize(attributes = {})
    super(attributes)
    @default1 = 'default value 1'
  end
end

但是,我发现这一般表达不太明显,并且取决于将来会阅读/维护此代码的人,我认为在set_constant_attributes方法中定义常量属性会更容易',而不是相信他们正确地覆盖init。

第三种方法是覆盖读者方法,这很简单,很简洁(现在我想起来,可能是我最喜欢的):

class MadagascarHedgehog
  def color
    'brown'
  end
end

答案 1 :(得分:0)

你可以制作一种制造马达加斯加刺猬的方法。

class Hedgehogs
  attr_accessor :name, :age, :color, :weight, :fur_quality, :disposition, :sexual_aggression, :has_syphilis

  def initialize(opts)
    @name = opts[:name] || 'Default Name'
    @age = opts[:age] || 'Default Age'
    ... etc ..
  end

  def self.madagascar_hedgehog
    self.new(:name => 'Madagascar', :age => 50)
  end
end

答案 2 :(得分:0)

首先,我认为您的课程应该是单数的,即HedgehogMadagascarHedgehog

你没有显示你的initialize方法,所以我想你要传递一个哈希,因为你有很多属性需要初始化。

假设您的主类看起来像这样

class Hedgehog

  attr_accessor :name, :age, :color, :weight, :fur_quality, :disposition, :sexual_aggression, :has_syphilis

end

然后你可以在你的子类中编写一个initialize方法来默认常量属性,并将值传递给超类进行实际的初始化。

您还可以禁用属性写入访问器,以便在使用undef_method时不会覆盖这些值。

class MadagascarHedgehog < Hedgehog

  def initialize(args)

    args[:color] = 'brown'
    args[:sexual_aggression] = 'aggressive'
    args[:has_syphilis] = 'immune'

    super(args)

  end

  undef_method :color=
  undef_method :sexual_aggression=
  undef_method :has_syphilis=

end