新手问题 如何在父类里调用子类实例方法?

cysh · 2016年04月30日 · 最后由 billy 回复于 2016年04月30日 · 3571 次阅读

= =!这句话还是放在前面好了… Spree 里的 Promotion Rule 就是这样的设计,实在没看懂为什么抛出一个 Exception 就能呼叫子类方法了?到底是怎么做到的呢…?


class Parent
  def method
    # do something
  end
end
class Sub < Parent
  def method
    # do something
  end
end

当我调用父类方法时,已知子类名,此时可以这么调用:

class Parent
  def method
    Object.const_get('Sub').class.new.method
  end
end

在这里又生成一个子类的实例,这里已经简化很多了,如果在 model 里实现的话,就还得去做一次查询,很麻烦,请问有没有办法在父类实例方法里呼叫子类的实现?(已知子类名,子类实例,但希望创建父类实例就能呼叫子类实现……

谢谢关注~望解答

这样做意义何在?

#1 楼 @adamshen Parent 定义方法,Sub 来实现,DB 里就只存一条数据,在读取数据的时候用 Parent 映射数据,但希望能用 Sub 的实例方法来处理数据,嗯,大概就是这样的需求,实现的方式是在表里加了 type 列,存的是子类名

可以在读取数据的时候根据 type 来实例化不同的子类?

#3 楼 @shallmentmo 你说的就是我的实现方式

Parent.all.map{|parent| Object.const_get(parent.type).find(id: parent.id).method } # 非常糟糕
  1. 如果你不需要创建子类就直接调用子类定义的方法,可以先获取子类方法对应的 UnboundMethod,然后 bind 到父类实例即可
  2. 不觉得这个有什么糟糕的,这实现不就是 ActiveRecord 的 STI 嘛?

不可以,不可以,不可以,三遍。

不是不能实现,是不可以。假设父类 A 调用子类 B 的方法,那么父类 A 的有效性依赖于子类 B。如果有另外的子类 C 继承于父类 A, 那么 C 也间接依赖 B。你的代码耦合成一坨坨。

正确的 OOP 实现里面,父类 A 不在乎谁来继承。另外的子类 C 完全无视 B 的存在。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号