How to access a class inside a class << self in Ruby? In the code sample, it's SecondClass.func which should be accessed.
class MainClass
class << self
class SecondClass
def self.func
p 'Hi!'
end
end
end
end
UPDATE
It can be accessed like:
MainClass.singleton_class::SecondClass.func
It can be accessed like:
MainClass.singleton_class::SecondClass.func
Related
attr_accessor does not work on the following code. The error says "undefined method 'things' for Parent:Class (NoMethodError)":
class Parent
##things = []
attr_accessor :things
end
Parent.things << :car
p Parent.things
However the following code works
class Parent
##things = []
def self.things
##things
end
def things
##things
end
end
Parent.things << :car
p Parent.things
attr_accessor defines accessor methods for an instance. If you want class level auto-generated accessors you could use it on the metaclass
class Parent
#things = []
class << self
attr_accessor :things
end
end
Parent.things #=> []
Parent.things << :car
Parent.things #=> [:car]
but note that this creates a class level instance variable not a class variable. This is likely what you want anyway, as class variables behave differently than you might expect when dealing w/ inheritance. See "Class and Instance Variables In Ruby".
attr_accessor generates accessors for instance variables. Class variables in Ruby are a very different thing, and they are usually not what you want. What you probably want here is a class instance variable. You can use attr_accessor with class instance variables like so:
class Something
class << self
attr_accessor :things
end
end
Then you can write Something.things = 12 and it will work.
Just some clarification: class variables won't be accessible using attr_accessor. It's all about instance variables:
class SomeClass
class << self
attr_accessor :things
end
#things = []
end
because in Ruby, class is an instance of the class "Class" (God, I love to say that) and attr_accessor sets accessor methods for instance variables.
This is probably the simplest way.
class Parent
def self.things
##things ||= []
end
end
Parent.things << :car
p Parent.things
Аlso note that a singleton method is a method only for a single object. In Ruby, a Class is also an object, so it too can have singleton methods! So be aware of when you might be calling them.
Example:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton methods of test_obj"
puts test_obj.singleton_methods
Singleton methods of SomeClass
test
Singleton methods of test_obj
test_2
test_3
Parent.class_variable_get(:##things)
That would be the built-in way. In most cases this should be sufficient I think. No need to have a class variable accessor in the instance.
class Parent
#things = []
singleton_class.send(:attr_accessor, :things)
end
This pattern is most useful when you are defining accessors dynamically or creating them inside a method:
class Foo
def self.add_accessor(name)
singleton_class.send(:attr_accessor, name)
end
end
Foo.add_accessor :things
Foo.things = [:car]
Foo.things # => [:car]
Here are the Ruby classes I have:
class MyBase
class << self
def static_method1
##method1_var ||= "I'm a base static method1"
end
def static_method1=(value)
##method1_var = value
end
def static_method2
##method2_var ||= "I'm a base static method2"
end
def static_method2=(value)
##method2_var = value
end
end
def method3
MyBase::static_method1
end
end
class MyChild1 < MyBase
end
class MyChild2 < MyBase
class << self
def static_method1
##method1_var ||= "I'm a child static method1"
end
end
end
c1 = MyChild1.new
puts c1.method3 #"I'm a base static method1" - correct
c2 = MyChild2.new
puts c2.method3 # "I'm a base static method1" - incorrect. I want to get "I'm a child static method1"
I'm aware of attr_accessor and modules, but I can't use use them here because I want them to give default values in MyBase class. I want to override MyBase.static_method1 in MyChild2.
The problem is that method3 is always explicitly calling the method on the base class. Change it to this:
def method3
self.class.static_method1
end
After that, consider not using ##.
## in ruby is extremely counterintuitive and rarely means what you think it means.
The problem with ## is that it is shared across the all of the inherited classes and the base class. See this blog post for an explanation.
I'm trying to mix a module into a class, and I want some of the methods to behave as class methods and others to be instance methods.
However, I don't want to both include and extend the module. I'd rather just include it.
When I wrap the methods I want to be class methods in this notation, it works:
class <<
# ...
end
However, when I use this notation it doesn't work:
class << self
# ...
end
I suspect the self keyword is establishing an explicit binding to the module, rather than the class it gets mixed into. But I've not seen any documentation that recommends leaving the self keyword off when using the class << notation.
Does anyone know what's going on with this?
UPDATE: Here's some sample code for more clarity:
module M
class <<
def class_method
puts "From inside the class_method"
end
end
def instance_method
puts "From inside the instance_method"
end
end
class Object
include M
end
class C
end
C.class_method
obj = C.new
obj.instance_method
class << must always be followed by an object. Just class <<; end is a syntax error. In your case it looks like it works because of the following:
class <<
def class_method
puts "From inside the class_method"
end
end
is the same as
class << def class_method
puts "From inside the class_method"
end
end
which is the same as
temp = def class_method
puts "From inside the class_method"
end
class << temp
end
which is the same as
def class_method
puts "From inside the class_method"
end
class << nil
end
which is the same as
def class_method
puts "From inside the class_method"
end
Of course that doesn't actually define a class method. It defines an instance method.
Yeah, if you want to get a real self in your module you should use included callback. Something like this point you in the right direction:
module Bar
def self.included(base)
class << base
def class_method
"class_method"
end
end
end
end
class Foo
include Bar
end
p Foo.class_method # => "class_method"
In Ruby. How do I refer to a class from within the class << self definition?
module MyModule
class MyClass
puts self # returns MyModule::MyClass
class << self
puts self # returns #<Class:MyModule::MyClass>
puts ???
end
end
end
How do I get the result MyModule::MyClass from where the ??? is?
Thanks,
Arth
Until somebody comes up with a more orthodox solution, nesting seems to do the work:
module MyModule
class MyClass
class << self
puts nesting[1] # MyModule::MyClass
end
end
end
In the following fragment, is it possible to refer to the FOO constant from outside the module, and if so, how?
module X
class << self
FOO = 2
end
end
class <<X
self
end::FOO
or
class Object
def metaclass
class <<self
self
end
end
end
X.metaclass::FOO