This question already has answers here:
What is Ruby's double-colon `::`?
(12 answers)
Closed 8 years ago.
what's the difference between class ClassName and class ::ClassName in ruby?
class ClassName
end
vs
class ::ClassName
end
Your two examples would make difference if the classes were defined inside a ruby module, so:
module Foo
class ClassName
end
end
would define a new class inside the Foo module. This could be accessed like Foo::ClassName.
On the other hand, this:
module Foo
class ::ClassName
end
end
would define (or monkey-patch) the class ClassName in the root namespace.
::Class says 'look for Class in top level namespace'. The difference shows when in context of a module.
module A
def foo
X.new
end
end
A.foo # => A::X.new
module B
def foo
::X.new
end
end
B.foo # => X.new
Related
I have a class within several modules: This::Is::A::Long::ClassName. Is there any way, within one script or method, to make ClassName available without having to reference the namespace? Instead of writing:
This::Is::A::Long::ClassName.do_something
This::Is::A::Long::ClassName.do_something_else
This::Is::A::Long::ClassName.do_something_different
is anything as below possible?
include This::Is::A::Long
ClassName.do_something
ClassName.do_something_else
ClassName.do_something_different
If you are using modules for namespacing, the code you posted should work, see this example:
module Long
module Name
class ClassName
end
end
end
ClassName
# => ... uninitialized constant ClassName (NameError)
include Long::Name
ClassName
# => Long::Name::ClassName
Ruby has no equivalent to C++ using namespace, and you can not reference a class without being in the right namespace, but you can always make it a variable since a class is also an object
long_class = This::Is::A::Long::ClassName
long_class.do_something
long_class.do_something_else
# and so on
EDIT
An include does not put you in the right namespace, it includes the methods & classes in the module you are including (that is, it puts the module in the classes ancestors) and is therefore most certainly not suitable for your needs: Consider the following:
module This
module Is
module A
def foo
puts 'A#foo'
end
def bar
puts 'A#bar'
end
class ClassName
end
end
end
end
Now, you may not want to write This::Is::A::ClassName in another class, let's say:
class C
def foo
puts 'C#foo'
end
end
class B < C
include This::Is::A
end
Now, B.new.foo still puts out C#foo, right? Wrong. Since you included the module, the method has been overwritten.
This question already has answers here:
What is Ruby's double-colon `::`?
(12 answers)
Closed 9 years ago.
I'm looking at the following code:
module Tag
def sync_taggings_counter
::Tag.find_each do |t|
# block here
end
end
end
and I'm confused by ::Tag inside the Tag module.
I know the double colon is used to name-space classes and modules within classes/modules. But I've never seen it used like the above. What does it mean exactly?
It's a scope modifier. Prefixing your constant (Tag) with a double colon ensures that you're looking in the root/global namespace instead of within your current module.
E.g.
module Foo
class Bar
def self.greet
"Hello from the Foo::Bar class"
end
end
class Baz
def self.scope_test
Bar.greet # Resolves to the Bar class within the Foo module.
::Bar.greet # Resolves to the global Bar class.
end
end
end
class Bar
def self.greet
"Hello from the Bar class"
end
end
The prepending is usually not neccessary as Ruby automatically looks in the global namespace, if it fails to find the referenced constant in the local module. So if no Bar existed in the Foo module, then Bar.greet and ::Bar.greet would do the exact same thing.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
class Check
include TestParser
# so on
end
and module structure:
module TestParser
class Array
def parse_test
# method
end
end
end
What I want to achieve is so that every array in file check.rb can be called by parse_test method.
Where I got it wrong? (throws undefined method error)
What you’re looking for is Ruby 2.0’s refinements. Note that this feature is experimental:
module TestParser
refine Array do
def parse_test
42
end
end
end
using TestParser # This applies only to the current file
class Check
[].parse_test #=> 42
end
You could also inherit from Array and add your method:
class TestParser < Array
def parse_test
42
end
end
arr = TestParser.new
arr.is_a? Array #=> true
arr.parse_test #=> 42
However, I strongly discourage doing either of these things. It would be better to make an object that encapsulates an Array and only provides the methods you need:
class TestParser
def initialize array = []
#array = array
end
def parse_test
# do stuff to #array
end
end
Finally, for why what you have does not work:
module TestParser
class Array
def parse_test; end
end
end
creates two things: a module TestParser with no methods and a class TestParser::Array with one method (parse_test). Since TestParser has no methods, including it into another Module/Class has no effect on the methods available. Including TestParser does not do anything with TestParser::Array.
You've defined a new class TestParser::Array containing the parse_test method; you have not modified the Array class.
You also may be confusing modules and inclusion.
If your goal is to add the method parse_test to arrays in your Ruby program, you can put this in a file called test_parser.rb, with no module declaration:
class Array
def parse_test
# method
end
end
But that will modify the base Array class, which you said you didn't want to do. Furthermore, it will make that modification as soon as the file is required. No inclusion is necessary.
Outside of a currently-experimental Ruby 2.0 feature called refinements, there's no way to localize those sorts of modifications to base classes (which is called "monkey patching").
If you want arrays to behave differently but only within your code, your best bet is to define your own class that extends Array (that is, make it a container class wrapping and delegating to a regular Array, or a subclass if you feel you must).
What I want to achieve is so that every array in file check.rb can be
called by parse_test method.
You just have to know how to create the array:
module TestParser
class Array
def parse_test
puts 'hello'
end
end
end
class Check
include TestParser
Array.new.parse_test
def do_stuff
Array.new.parse_test
end
end
Check.new.do_stuff
Check::Array.new.parse_test
--output:--
hello
hello
hello
Of course, the TestParser::Array class has none of the methods found in the Array class:
module TestParser
class Array
def parse_test
puts 'hello'
end
end
end
TestParser::Array.new.parse_test
TestParser::Array.new.size
--output:--
hello
1.rb:11:in `<main>': undefined method `size' for #<TestParser::Array:0x00000101141700> (NoMethodError)
That's because you created a new Array class inside the namespace TestParser--you did not reopen ruby's built in Array class.
Then when you write include TestParser, that is equivalent to doing this:
class AnonymousClass
class Array
def parse_test
puts 'hello'
end
end
end
class Check < AnonymousClass
Array.new.parse_test
end
And when a constant isn't found in Check, ruby goes up the inheritance chain looking for the constant:
class Parent
CONST = 10
end
class Child < Parent
puts CONST
end
--output:--
10
Because the built in Array class is a constant that lives at the very top of the inheritance chain, the Array constant in AnonymousClass hides the ruby built in Array class. To refer to the ruby built in Array class, you have to write ::Array:
module TestParser
class Array
def parse_test
puts 'hello'
end
end
end
class Check
include TestParser
p Array
p ::Array
end
--output:--
TestParser::Array
Array
And for the coup-de-grace*:
module TestParser
class Array
def parse_test
puts 'hello'
end
end
end
class Check
include TestParser
end
puts TestParser::Array.object_id
puts Check::Array.object_id
--output:--
2152779400
2152779400
*coup de grace: a death blow to end the suffering of a severely wounded person or animal
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Look up all descendants of a class in Ruby
So, let's say that we have:
class LivingBeing
class Animal
end
class Bacteria
end
class Virus
end
end
class Fungi < LivingBeing
end
How do I check what subclasses LivingBeing has? I know that we have Klass.ancestors but what's the method to see the opposite of ancestors?
There's nothing built into the core Ruby language that will do what you want - you'll need to write your own. Here's an example method subclasses_of(class_name_here) (below) that will return a list of subclasses of a particular class for you:
class Mammal
end
class Human < Mammal
end
class Dog < Mammal
end
def subclasses_of input
ObjectSpace.each_object(Class).select { |klass| klass < input }
end
subclasses_of(Mammal)
#=> [Human, Dog]
Btw, there's an answer to this question here:
http://dzone.com/snippets/objectsubclasses
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is the difference between include and extend in Ruby?
Given:
module my_module
def foo
...
end
end
Question 1
What is the difference between:
class A
include my_module
end
and
class A
extend my_module
end
Question 2
Will foo be considered an instance method or a class method ?
In other words, is this equivalent to:
class A
def foo
...
end
end
or to:
class A
def self.foo
...
end
end
?
I wrote a blog posting about this a long time ago here.
When you're "including" a module, the module is included as if the methods were defined at the class that's including them, you could say that it's copying the methods to the including class.
When you're "extending" a module, you're saying "add the methods of this module to this specific instance". When you're inside a class definition and say "extend" the "instance" is the class object itself, but you could also do something like this (as in my blog post above):
module MyModule
def foo
puts "foo called"
end
end
class A
end
object = A.new
object.extend MyModule
object.foo #prints "foo called"
So, it's not exactly a class method, but a method to the "instance" which you called "extend". As you're doing it inside a class definition and the instance in there is the class itself, it "looks like" a class method.
1) include adds methods, constants, and variables on instances of class A; extend adds those things to the instance of the Class instance A (effectively defining class methods).
include my_module will allow this: A.new.foo
extend my_module will allow this: A.foo
More generally, include only makes sense on a Class or Module, while extend can be used to add methods to any Object.
2) In effect: when using include, foo is an instance method of A ... when using extend, foo is a class method.