• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Ruby类继承、抽象类、类拓展混入、代理类实例

    总结一下工作中遇到的类扩展:

    1、类继承:

    当多个类公用很多方法的时候可以将公用方法部分抽取出来,需要的类做相关继承。

    例子:

    复制代码 代码如下:

    class A ActiveRecord::Base
        def a
            p "it was a "
        end
    end

    class BA
    end

    class CA
    end

    B.new.a #=>"it was a "
    C.new.a #=>"it was a "

    2、抽象类

    当多个类要继承一个类时,用第一种方法,会遇到一个问题。
    (引用一个别人的注解来描述抽象类的运用吧https://ihower.tw/rails4/activerecord-others.html)

    單一表格繼承STI(Single-table inheritance)

    如何將物件導向中的繼承概念,對應到關聯式資料庫的設計,是個大哉問。Rails內建了其中最簡單的一個解法,只用一個資料表儲存繼承體系中的物件,搭配一個type欄位用來指名這筆資料的類別名稱。

    要開啟STI功能,依照慣例只要有一個欄位叫做type,型態字串即可。假設以下的posts資料表有欄位叫做type,那麼這三個Models實際上就會共用posts一個資料表,當然,還有這兩個子類別也都繼承到父類別的validates_presence_of :subject:

    复制代码 代码如下:

    class Post ActiveRecord::Base 
        validates_presence_of :subject 
    end 
     
    class GuestPost Post 
    end 
     
    class MemberPost Post 
    end 

    讓我們進入rails console實驗看看,Rails會根據你使用的類別,自動去設定type欄位:

    复制代码 代码如下:

    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

    复制代码 代码如下:

    class Post ActiveRecord::Base 
        self.abstract_class = true 
    end 
     
    class GuestPost Post 
    end 
     
    class MemberPost Post 
    end 

    這裡的GuestPost和MemberPost就需要有自己的Migrations建立guest_posts和member_posts資料表。

    你还可以在某个类中,引入多个依赖

    复制代码 代码如下:

    class DependencyPost 
        require_dependency 'guestpost' 
        require_dependency 'memberpost' 
    end 

    3、类拓展混入

    ruby的类是单继承的,要实现多继承的功能需要用mixin(参合模式)的方式,即类拓展混入来实现。例子:

    复制代码 代码如下:

    module Extract 
      def self.included(base) 
         base.extend(ClassMethods) 
      end 
      module ClassMethods 
         def a 
            p "it was a " 
         end 
      end 
    end   
     
    class AActiveRecord::Base 
      include Extract 
    end 
     
    A.new.a  #=>"it was a" 

    4、代理类

    当某个功能是比较复杂的,当然写再lib中,作为一个面向函数的方法去处理很简单,也可以用代理类的方式实现面向对象的调用。

    例子:

    复制代码 代码如下:

    class AActiveRecord::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的方式实现添加类实例方法,有时候也可以混合使用。另外使用代理类的好处在于多个类都需要相同方法的时候可以定义共同的部分,举一个发邮件的例子:

    复制代码 代码如下:

    class AActiveRecord::Base
        include SendEmail
    end

    class BActiveRecord::Base
        include SendEmail
    end

    实现引入模块:

    复制代码 代码如下:

    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

    实现代理类:

    复制代码 代码如下:

    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很灵活当然还有很多其他的方法实现更多的方式,以后再慢慢总结。

    您可能感兴趣的文章:
    • Ruby最简单的消息服务器代码
    • 浅析Ruby中继承和消息的相关知识
    上一篇:openSUSE下的Ruby安装openssl出错解决方法
    下一篇:Rails中遇到错误跳转到统一提示错误页的方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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