I would like to understand what class << self stands for in the next example.
module Utility
class Options #:nodoc:
class << self
def parse(args)
end
end
end
end
this
module Utility
class Options #:nodoc:
class << self
# we are inside Options's singleton class
def parse(args)
end
end
end
end
is equivalent to:
module Utility
class Options #:nodoc:
def Options.parse(args)
end
end
end
A couple examples to help you understand :
class A
HELLO = 'world'
def self.foo
puts "class method A::foo, HELLO #{HELLO}"
end
def A.bar
puts "class method A::bar, HELLO #{HELLO}"
end
class << self
HELLO = 'universe'
def zim
puts "class method A::zim, HELLO #{HELLO}"
end
end
end
A.foo
A.bar
A.zim
puts "A::HELLO #{A::HELLO}"
# Output
# class method A::foo, HELLO world
# class method A::bar, HELLO world
# class method A::zim, HELLO universe
# A::HELLO world
This is an eigenclass. This question's been asked before.
Related
class Main
def say_hello
puts "Hello"
end
private
def say_hi
puts "hi"
end
end
class SubMain < Main
def say_hello
puts "Testing #{say_hi}"
end
end
test = SubMain.new
test.say_hello()
OUTPUT:
hi
Testing
The difference is that in ruby you can call private methods in subclasses implicitly but not explicitly. Protected can be called both ways. As for why? I guess you would have to ask Matz.
Example:
class TestMain
protected
def say_hola
puts "hola"
end
def say_ni_hao
puts "ni hao"
end
private
def say_hi
puts "hi"
end
def say_bonjour
puts "bonjour"
end
end
class SubMain < TestMain
def say_hellos
# works - protected/implicit
say_hola
# works - protected/explicit
self.say_ni_hao
# works - private/implicit
say_hi
# fails - private/explicit
self.say_bonjour
end
end
test = SubMain.new
test.say_hellos()
A small test case :
class A
def self.print
puts "Hello A"
end
end
class B < A
end
A.print
B.print
This outputs :
Hello A
Hello A
I would like to block the inheritance of the print function defined in class A. Is it possible?
Output wanted :
Hello A
`<main>': undefined method `print' for B:Class (NoMethodError)
I found private_class_method but it's not exaclty what I'm looking for as it fails on A.print call.
class A
def self.print
puts "Hello A"
end
def self.inherited(klass)
class << klass
undef :print
end
end
end
class B < A
end
A.print
# Hello A
B.print
# private method `print' called for B:Class (NoMethodError)
class B < A
class << self
undef print
end
end
Declaring a method in a class << self block is the same as declaring it prefixed with self..
It also allows for the behavior that you want.
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
I have the following Ruby script, in which class Foo includes module Baz, module Baz has a included hook to make Bar extended by the including class (Foo). I am just wondering why:
class << klass
extend Bar #this doesn't work. Why?
end
does not work while:
klass.extend(Bar) works.
Here is my code:
#! /usr/bin/env ruby
module Baz
def inst_method
puts "dude"
end
module Bar
def cls_method
puts "Yo"
end
end
class << self
def included klass
# klass.extend(Bar) this works, but why the other approach below doesn't?
class << klass
extend Bar #this doesn't work. Why?
def hello
puts "hello"
end
end
end
end
end
class Foo
include Baz
end
foo = Foo.new
foo.inst_method
Foo.hello
Foo.cls_method
Within the body of class << klass, self refers to the singleton class of klass, not klass itself, whereas in klass.extend(Bar), the receiver is klass itself. The difference comes from there.
class A
end
class << A
p self # => #<Class:A> # This is the singleton class of A, not A itself.
end
p A # => A # This is A itself.
And since you want to apply extend to klass, doing it within the body of class << klass does not work.
What you want is invoke the extend method on the class object (klass) not the singleton class (class << klass).
Therefore the following code doesn't work because you are invoking the extend method on the singleton class:
class << klass
extend Bar # doesn't work because self refers to the the singleton class of klass
def hello
puts "hello"
end
end
I'm trying to make a method similar to attr_reader but I can't seem to get the instance of the class that the method gets called in.
class Module
def modifiable_reader(*symbols)
# Right here is where it returns Klass instead of #<Klass:0x1df25e0 #readable="this">
mod = self
variables = symbols.collect { |sym| ("#" << sym.to_s).to_sym }
attr_reader *symbols
(class << ModifyMethods; self; end).instance_eval do
define_method(*symbols) do
mod.instance_variable_get(*variables)
end
end
end
end
class Object
module ModifyMethods; end
def modify(&block)
ModifyMethods.instance_eval(&block)
end
end
class Klass
modifiable_reader :readable
def initialize
#readable = "this"
end
end
my_klass = Klass.new
my_klass.modify do
puts "Readable: " << readable.to_s
end
I'm not sure what it is you're trying to do.
If it helps, the spell for attr_reader is something like this:
#!/usr/bin/ruby1.8
module Kernel
def my_attr_reader(symbol)
eval <<-EOS
def #{symbol}
##{symbol}
end
EOS
end
end
class Foo
my_attr_reader :foo
def initialize
#foo = 'foo'
end
end
p Foo.new.foo # => "foo"
What I can understand from your code is that you want to have the modify block to respond to the instance methods of Klass, that's as simple as:
class Klass
attr_reader :modifiable
alias_method :modify, :instance_eval
def initialize(m)
#modifiable = m
end
end
Klass.new('john').modify do
puts 'Readable %s' % modifiable
end
About this tidbit of code:
def modifiable_reader(*symbols)
# Right here is where it returns Klass instead of #<Klass:0x1df25e0 #readable="this">
mod = self
...
Probably this can give you a hint of what is going on:
Class.superclass # => Module
Klass.instance_of?(Class) # => true
Klass = Class.new do
def hello
'hello'
end
end
Klass.new.hello # => 'hello'
When you are adding methods to the Module class, you are also adding methods to the Class class, which will add an instance method to instances of Class (in this case your class Klass), at the end this means you are adding class methods on your Klass class