Skip to content

Instantly share code, notes, and snippets.

@mifix
Last active December 17, 2015 06:08
Show Gist options
  • Save mifix/5562875 to your computer and use it in GitHub Desktop.
Save mifix/5562875 to your computer and use it in GitHub Desktop.
# see http://blog.codegram.com/2011/4/understanding-class-instance-variables-in-ruby
# and http://vimeo.com/33481092 (Ruby's Object Model & Eigenclasses)
module MyMixin
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
# the current class (also called definee or klass) determines on
# which class 'def' will act on
#
# definee => MyMixin::ClassMethods
#
def set(value)
# self points to the current object (also called callee), it
# determines on which object a method is called
#
# self => either A or B
#
@@my_value = value
end
def get
@@my_value
end
end
end
class A
include MyMixin
set 'Test from A'
end
class B
include MyMixin
set 'Test from B'
end
# we have overwritten MyMixin::ClassMethods::@@my_value
A.get # => "Test from B"
# methods are defined in module
A.singleton_methods # => [:set, :get]
A.singleton_methods(false) # => []
A.class_variables # => []
MyMixin::ClassMethods.class_variables # => [:@@my_value]
## Summary:
#
# 'set', 'get' methods are defined in: A's singleton class
# 'my_value' is defined in: MyMixin::ClassMethods as class var
###################### ######################
module YourMixin
def self.included(base)
# define_singleton_method essentially means the following:
#
# base.singleton_class.send :define_method, :set do ...; end
#
# 'define_method' cares only about 'self' not the current class
#
# We're creating a singleton method without using 'class' or 'self'
# which means, we are not forced into a new scope
base.define_singleton_method :set do |value|
@my_value = value
end
base.define_singleton_method :get do
@my_value
end
end
end
class C
include YourMixin
set 'Test from C'
end
class D
include YourMixin
set 'Test from D'
end
C.get # => "Test from C"
# methods are defined in the class' singleton class
C.singleton_methods(false) # => [:set, :get]
C.class_variables # => []
C.instance_variables # => [:@my_value]
## Summary:
#
# 'set', 'get' methods are defined in: C's singleton class
# 'my_value' is defined as C's class instance variable
###################### ######################
module HerMixin
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def set(value)
class_variable_set '@@my_value', value
end
def get
class_variable_get '@@my_value'
end
end
end
class E
include HerMixin
set 'Test from E'
end
class F
include HerMixin
set 'Test from F'
end
E.get # => "Test from E"
E.singleton_methods(false) # => []
E.class_variables # => [:@@my_value]
## Summary:
#
# 'set', 'get' methods are defined in: HerMixin module
# 'my_value' is defined in: E as class var
###################### ######################
module HisMixin
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def set(value)
@my_value = value
end
def get
@my_value
end
end
end
class G
include HisMixin
set 'Test from G'
end
class H
include HisMixin
set 'Test from H'
end
H.get # => "Test from H"
H.singleton_methods(false) # => []
H.class_variables # => []
H.instance_variables # => [:@my_value]
## Summary:
#
# 'set', 'get' methods are defined in: HisMixin module
# 'my_value' is defined as H's class instance variable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment