Rails 如何才能很好地继承类,但又避免重复编码?

kevinhua · March 26, 2012 · Last by poshboytl replied at March 27, 2012 · 3472 hits

以 Ruby China 的源代码为例,可以

继承 Model

class Movie < Topic
  ... ...
end

继承 Controller

class MoviesController < TopicsController
  ... ...
end

问题是: (1) MoviesController 中有必要复写 TopicsController 的方法吗?如果不复写,因为 Topics 中使用的是 Topic 类和@topic实例,如何才能自动使用 Movie 类和@movie实例。 (2) Views 又如何实现较为 DRY 的继承?

你这根本不是 Rails 的目的。而是 Ruby 的问题。貌似放错分类了吧?

(1) 当然没必要重写。 这个问题证明你还是对多态性还不甚了解。本身这个问题就不好回答,也不是一个好问题。 覆写不覆写,要看你要做什么。你可以覆写,也可以通过 super 调用,还可以通过设定不同的可见性来方便的调用超类的实例。但是总的来说,如果仅仅为了分享代码,在 Ruby 下面。首选混入同一个模块。

(2) Views 干嘛实现继承?

views 若真的不想复写,可以通过 render 的方式来避免. 按你的例子,如果你想复用 topics 的 show 页面,可以在 movies/show.html.erb 中直接 render :file => 'topics/show'.

controller 继承只在两种情况下用过,一个是为了 layout,另外一个是偷懒少写相同的 create 什么的,也就是 inherited_resources 这个 gem 干的事情。

inherited_resources 已经在 README 里已经放出了deprecation notice了,直接推荐使用 responders.

**Deprecation notice**
Since Rails 3 came out, I have no longer used Inherited Resources. I have found that the responders abstraction and custom Rails generators offer the perfect balance between hiding and showing too much logic. That said, I suggest developers to make use of the responders gem (at github.com/plataformatec/responders) and no longer use Inherited Resources.


如果没有什么特殊原因的话,最好少用继承。 继承虽好,但不能滥用。

如果你要定义一个新的 model movie 的话, 首先我建议你先不要用继承,model 层和 controller 层都先不要继承。

先从没有继承的结构开始编码, 编码完成后,如果发现重复度很高的话, 可以考虑提取共用的函数。

其次,给你个建议, controller 的 action 最好不要定义在基类中, 否则代码会很混乱,这种混乱带来的危害, 远远高于,因为继承,代码量减少,所带来的好处, 正所谓得不偿失

避免重复编码 这个原则 要有一个尺度,不能太过分。

真爱生命,远离 OO,拥抱 FP

如果只看 Movie < Topic,那么我的理解就是多表继承,如果是多表继承,那么只需要写 topic 的 controller 和 view,路由里多写几条 resources,controller 和 view 中使用 [xx,xx] 的方式来写路由就 ok

#1 楼 @kevinhua 不用刻意要求自己,多写,熟能生巧。写多了你就会想怎么减少代码量,避免重复代码,重复逻辑,提高复用程度。 别人的代码风格也不用太深究,一时发挥而已,一个 forum,我相信你自己梳理一下思路,也能够实现个大概,此时再去看看别人的写得好点的代码,再学习是很有用的。

楼主你 model 是在做单表继承吗?这没任何问题,虽然看起来 Movie 和 Topic 不太像一个继承关系。 我之所以会这么问是因为,我认为共享方法只是一个结果,而不是单纯为了共享方法而去继承一下。共享方法的方式有很多,而用继承那么应该是因为他们有着一种“继承”的关系。听起来好绕 :D

关于 controller 部分,我觉得这里没必要做继承。原因就是 MoviesController 和 TopicsControllerm 没有继承关系。有的是他们的 model,而不是他们的 controller。

补充一点就是,action 本身并不应该在多个 controller 里共享。如果一定有需求,就写一个类似 BaseController 的东西,让其它 controller 继承它。

如果 controller 里有非 action 的方法需要共享可以考虑是否能放在 application controller。

忘记回答你第二个问题了。view 的重用就用 partial 吧...

You need to Sign in before reply, if you don't have an account, please Sign up first.