Ruby class instance variables and inheritance

前端 未结 9 617
日久生厌
日久生厌 2020-12-28 08:02

I have a Ruby class called LibraryItem. I want to associate with every instance of this class an array of attributes. This array is long and looks something lik

相关标签:
9条回答
  • 2020-12-28 08:45

    To expand on @Nick Vanderbilt's answer, using active_support you do this, which is exactly the short hand I want for this functionality. Here's a complete example:

    require 'active_support/core_ext'
    
    class Foo
      class_attribute :attributes
      self.attributes = ['title','authors','location']
    end
    
    class Bar < Foo
      self.attributes = Foo.attributes + ['ISBN', 'pages']
    end
    
    puts Foo.attributes.inspect #=> ["title", "authors", "location"]
    puts Bar.attributes.inspect #=> ["title", "authors", "location", "ISBN", "pages"]
    

    Shame it's so difficult for ruby to achieve this without needing a library for it. It's the only thing I miss from python. And in my case, I don't mind the dependency on the active_support gem.

    0 讨论(0)
  • 2020-12-28 08:45

    This is for strings (anything really), rather than arrays, but...

    class A
      def self.a
        @a || superclass.a rescue nil
      end
    
      def self.a=(value)
        @a = value
      end
    
      self.a = %w( apple banana chimp )
    end
    
    class B < A
    end
    
    class C < B
      self.a += %w( dromedary elephant )
    end
    
    class D < A
      self.a = %w( pi e golden_ratio )
    end
    
    
    
    irb(main):001:0> require 'test2'
    => true
    irb(main):002:0> A.a
    => ["apple", "banana", "chimp"]
    irb(main):003:0> B.a
    => ["apple", "banana", "chimp"]
    irb(main):004:0> C.a
    => ["apple", "banana", "chimp", "dromedary", "elephant"]
    irb(main):005:0> D.a
    => ["pi", "e", "golden_ratio"]
    irb(main):006:0> A.a = %w( 7 ) 
    => ["7"]
    irb(main):007:0> A.a
    => ["7"]
    irb(main):008:0> B.a
    => ["7"]
    irb(main):009:0> C.a = nil
    => nil
    irb(main):010:0> C.a
    => ["7"]
    
    0 讨论(0)
  • 2020-12-28 08:46

    Another solution would be to use the inherited hook:

    class LibraryItem < Object
      class << self
        attr_accessor :attributes
        def inherit_attributes(attrs)
          @attributes ||= []
          @attributes.concat attrs
        end
    
        def inherited(sublass)
          sublass.inherit_attributes(@attributes)
        end
      end
      @attributes = ['title', 'authors', 'location',]
    end
    
    class LibraryBook < LibraryItem
      @attributes.push('ISBN', 'pages')
    end
    
    0 讨论(0)
  • 2020-12-28 08:46

    ActiveSupport has class_attribute method in rails edge.

    0 讨论(0)
  • 2020-12-28 08:51

    In LibraryBook variable @attributes is a new independent variable, instance variable of object LibraryBook, so its not initialized and you get error "undefined method ... for nil"
    You should to initialize it by LibraryItem attribut's list before using

    class LibraryBook < LibraryItem
      @attributes = LibraryItem::attributes + ['ISBN', 'pages']
    end
    
    0 讨论(0)
  • 2020-12-28 08:52

    You can do it using CONSTANTS also. No check though.

    class LibraryItem < Object
      class << self; attr_accessor :attributes; end
      ATTRIBUTES = ['title', 'authors', 'location',]
    end
    
    class LibraryBook < LibraryItem
      ATTRIBUTES .push('ISBN', 'pages']
    end
    
    0 讨论(0)
提交回复
热议问题