源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Ruby类继承、抽象类、类拓展混入、代理类实例

  • 时间:2021-10-01 21:23 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Ruby类继承、抽象类、类拓展混入、代理类实例
总结一下工作中遇到的类扩展: [b]1、类继承: [/b] 当多个类公用很多方法的时候可以将公用方法部分抽取出来,需要的类做相关继承。 例子:
[u]复制代码[/u] 代码如下:
class A < ActiveRecord::Base     def a         p "it was a "     end end class B<A end class C<A end B.new.a #=>"it was a " C.new.a #=>"it was a "
[b]2、抽象类 [/b] 当多个类要继承一个类时,用第一种方法,会遇到一个问题。 (引用一个别人的注解来描述抽象类的运用吧https://ihower.tw/rails4/activerecord-others.html) 單一表格繼承STI(Single-table inheritance) 如何將物件導向中的繼承概念,對應到關聯式資料庫的設計,是個大哉問。Rails內建了其中最簡單的一個解法,只用一個資料表儲存繼承體系中的物件,搭配一個type欄位用來指名這筆資料的類別名稱。 要開啟STI功能,依照慣例只要有一個欄位叫做type,型態字串即可。假設以下的posts資料表有欄位叫做type,那麼這三個Models實際上就會共用posts一個資料表,當然,還有這兩個子類別也都繼承到父類別的validates_presence_of :subject:
[u]复制代码[/u] 代码如下:
class Post < ActiveRecord::Base      validates_presence_of :subject  end    class GuestPost < Post  end    class MemberPost < Post  end 
讓我們進入rails console實驗看看,Rails會根據你使用的類別,自動去設定type欄位:
[u]复制代码[/u] 代码如下:
post = GuestPost.create( :subject => "guest") post.type # "GuestPost" post.id # 1 post = MemberPost.create( :subject => "member" ) post.id # 2 post.type # "MemberPost" GuestPost.last # 1
很遺憾,也因為這個慣例的關係,你不能將type這麼名字挪做它用。 STI最大的問題在於欄位的浪費,如果繼承體系中交集的欄位不多,那麼使用STI就會非常的浪費空間。如果有較多的不共用的欄位,筆者會建議不要使用這個功能,讓個別的類別有自己的資料表。要關閉STI,請父類別加上self.abstract_class = true
[u]复制代码[/u] 代码如下:
class Post < ActiveRecord::Base      self.abstract_class = true  end    class GuestPost < Post  end    class MemberPost < Post  end 
這裡的GuestPost和MemberPost就需要有自己的Migrations建立guest_posts和member_posts資料表。 你还可以在某个类中,引入多个依赖
[u]复制代码[/u] 代码如下:
class Dependency<Post      require_dependency 'guestpost'      require_dependency 'memberpost'  end 
[b]3、类拓展混入[/b] ruby的类是单继承的,要实现多继承的功能需要用mixin(参合模式)的方式,即类拓展混入来实现。例子:
[u]复制代码[/u] 代码如下:
module Extract    def self.included(base)       base.extend(ClassMethods)    end    module ClassMethods       def a          p "it was a "       end    end  end      class A<ActiveRecord::Base    include Extract  end    A.new.a  #=>"it was a" 
[b]4、代理类 [/b] 当某个功能是比较复杂的,当然写再lib中,作为一个面向函数的方法去处理很简单,也可以用代理类的方式实现面向对象的调用。 例子:
[u]复制代码[/u] 代码如下:
class A<ActiveRecord::Base  def generate_schedule     generator =  Generator::ExcelGenerator.new(self)     generator.generate_schedule   end end module Generator   class ExcelGenerator     attr_reader :excel,:workbook,:a,:worksheet     attr_accessor :styles     def initialize(a)       @excel ||= Axlsx::Package.new       @workbook ||= @excel.workbook       @worksheet = @workbook.add_worksheet(:name => '测试生成一个excel文件')       @a ||= a       @styles ||= Hash.new     end         def generate_schedule         #excel内容的具体定义     end   end end A.new.generate_schedule 就可以通过代理类ExcelGenerator实现一个A的类实例方法generate_schedule
当然也可以通过include 一个model的方式实现添加类实例方法,有时候也可以混合使用。另外使用代理类的好处在于多个类都需要相同方法的时候可以定义共同的部分,举一个发邮件的例子:
[u]复制代码[/u] 代码如下:
class A<ActiveRecord::Base     include SendEmail end class B<ActiveRecord::Base     include SendEmail end
实现引入模块:
[u]复制代码[/u] 代码如下:
module SendEmail     #include this module to class::A and B     #use like that--  A.first.send_email     def send_email       Email.call_email(self)     end end
实现代理类:
[u]复制代码[/u] 代码如下:
class Email < ActionMailer::Base   default :from => "test@email.com"   def self.call_email(obj)      define_method "#{obj.state}" do |obj|        @obj = obj        mail(:to => @obj.email, :subject => "XX标题" )      end      send("#{obj.state}").deliver      #根据不同对象obj.state得到不同状态下,定义不同方法,然后send派发调用相关对象状态的模板。   end      end
RUBY很灵活当然还有很多其他的方法实现更多的方式,以后再慢慢总结。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部