Today I came across the Pathname class in Ruby and noticed that you could directly call the class itself as a method (which would basically return a new instance):
Pathname("some/path")
# => #<Pathname:some/path>
I've been trying to replicate the same thing with my CustomClass but haven't been successful. I don't know what these methods are called and I can't find any Ruby code that gives me an idea on how to do this. My Question is how do I use the Class name as method?
Things I've tried so far:
Defining self.self()
Defining self.class()
Using the class << self syntax
Googling - But it just returns comparisons of class methods vs instance methods
This isn't using the class itself. This is calling a method in Kernel with the same name as the class. It's generally discouraged to do it yourself as you pollute almost all objects with new methods and leads to confusion (as you already see).
Here is the documentation for the method. There are a few others like Array, Hash, String, etc.
What you're looking for is a conversion method to coerce the input to the instance of the class.
It is not a method of the class itself, but a method in Kernel module. So in order to be able to use the form of MyClass(value) you should add the method to Kernel module:
module Kernel
def Foo(value)
# you can implement any logic here
value.is_a?(Foo) ? value : Foo.new(value)
end
module_function :Foo
end
class Foo
def initialize(bar)
#bar = bar
end
end
baz = Foo('bar')
#=> #<Foo:0x007fd4e5070370 #bar="bar">
Foo(baz)
#=> #<Foo:0x007fd4e5070370 #bar="bar">
baz == Foo(baz)
#=> true
This is not a class call, but a shortcut. And the trickiest part - it was defined for a Kernel module to be available everywhere in the form as you just specified.
Please proceed to the link of the official docs. There you can see, that requiring a Pathname module, it extend Kernel module to add the method of the same name.
To be honest, I strongly recommend against extending Kernel with your own method. Or at least to use refinements
Related
I am having trouble with some fundamental concepts in Ruby, specifically the interchangeability of a subclass for the superclass.
According to the Ruby documentation on classes, "Class" inherits from "Module".
https://ruby-doc.org/core-2.5.3/Class.html
class MyClassTest end
MyClassTest.is_a? Module # => true
However, when trying to use the module keyword to reopen a class defined with the keyword class, you get a TypeError that the class is not a module.
class MyClassTest end
module MyClassTest end # => TypeError: MyClassTest is not a module
This SO question has some excellent discussion surrounding subclasses vs subtypes, but I think it has lead me to more questions:
Why can't classes be used as modules?
Generally, since Ruby is dynamically typed, I am confused by the existence of TypeErrors.
Specifically, in this case, I am extra confused as to how Ruby inheritance can result in a TypeError where the subclass cannot be substituted for the superclass. In my mind, subclassing is equivalent to subtyping in Ruby since the subclass will inherit the interface (methods and public attributes) of the superclass.
My current guess is that TypeError's are raised by the core Ruby library when certain assertions fail, and these TypeErrors don't necessarily have anything to do with Ruby's dynamic typing system, which is to say that typing is not a first-class concept in Ruby. The linked SO question raises excellent points about the diamond problem with multiple class inheritance, so it makes sense that Ruby would prevent the interchangeable usage of modules and classes when using the module or class keyword. Still, it feels like there are inconsistencies in my understanding of Ruby.
How can a "Class" input result in a TypeError when a "Module" object is expected?
Basic assertions are
Class is a Class (Class.is_a?(Class) #=> true)
Class is a Module (Class.is_a?(Module) #=> true)
An instance of the class Class is a Class (Class.new.is_a?(Class) #=> true)
An instance of the class Class is a Module (Class.new.is_a?(Module) #=> true)
Module is a Class (Module.is_a?(Class) #=> true)
By virtue Module is a Module (Module.is_a?(Module) #=> true)
An instance of the class Module is a Module (Module.new.is_a?(Module) #=> true)
However An instance of the class Module is not a Class (Module.new.is_a?(Class) #=> false)
an instance of the class Class is an instance of Class but not and instance of the class Module (Class.new.instance_of?(Module) #=> false)
module is a declaration for an instance of the class Module just as class is a declaration for an instance of the class Class.
If this were a method it might look like
def module(name,&block)
raise TypeError if defined?(name) && !const_get(name).instance_of?(Module)
obj = defined?(name) ? const_get(name) : const_set(name, Module.new)
obj.instance_eval(&block)
end
TypeError exists to prevent ambiguity.
As in your case by using class MyClassTest you have created an instance of the class Class and that instance is called MyTestClass.
If you were also allowed to use module MyTestClass, in the same global context, then during usage I would be unaware if when calling MyClassTest I would be calling the Class or the Module.
The basic (very basic) difference is a Class can be instantiated (have instances) however a Module cannot.
For instance
Class.new.new #creates an instance of the anonymous class created by Class.new
Module.new.new # results in NoMethodError
I think the first point of confusion is the distinction between usage and definition.
The following code defines a class:
class C; end
If I see the above code, I expect to be able to instantiate C later:
C.new
However, imagine that C was already defined as a module:
# In one file:
module C; end
# Later in a different file:
class C; end # C is actually a module
C.new # fails
Ruby surfaces the problem (conflicting definitions of C) at the point where C is redefined as a class, rather than allowing the program to continue to where C is used.
The benefit of surfacing the problem earlier is generally the earlier an error is identified, the easier it is to find and fix its root cause (in this example, perhaps C is supposed to be a class after all, and thus the real issue is the module C definition).
Your second question is, I think, why a class cannot always be used as a module, for example why the following is prohibited:
class C; end
class A
include C
end
The answer, I think, is the programming language starts with concepts which are then implemented using various constructs. We could describe classes and modules as follows:
A class represents an object which has data and behavior (classic OOP definition).
A module is a collection of behavior.
The include keyword extends a class with a module's behavior. In principle it is possible to take just a class's methods and add them to another class. But this operation doesn't make sense because a class is an object and its behavior together. Taking just the behavior goes against the concept of the class.
There are other programming languages which take different positions on this issue. For example, in JavaScript any function can be taken out of any class and invoked with an instance of any other class. This can be convenient in some situations and difficult to debug in others.
Learning ruby and oop in general, I came upon class methods which as far as I understand are like instance methods but are accessed from the class rather than from an object and can have only one running at the same time.
However, I don't understand why you would use a class method versuses a normal method (outside a class) and what is even their use?
For example:
#Why would you use:
class Foo
def self.bar
puts "Class method"
end
end
#Versus simply:
def bar
puts "Normal method"
end
Foo.bar # => Class method
bar # => Normal method
As they both produce the same result?
I'm quite confused about them so please correct if I'm misunderstanding any/everything here.
Your example isn't a good one.
Class methods might deal with managing all instances that exist of a class, and instance methods deal with a single instance at a time.
class Book
def self.all_by_author(author)
# made up database call
database.find_all(:books, where: { author: author }).map do |book_data|
new book_data # Same as: Book.new(book_data)
end
end
def title
#title
end
end
books = Book.all_by_author('Jules Vern')
books[0].title #=> 'Journey to the Center of the Earth'
In this example we have a class named Book. It has a class method all_by_author. It queries some pretend database and returns an array of Book instances. The instance method title fetches the title of a single Book instance.
So the class method managing a collection of instances, and the instance method manages just that instance.
In general, if a method would operate on a group of instances, or is code related to that class but does not directly read or update a single instance, then it probably should be a class method.
This is more an OOP question than a ruby one. Class methods in ruby are used the same as in other OO programming languages. This means:
class methods are run in the context of a class (and have access only to class variables)
instance methods are run in the context of an object (and have access to object's or instance variables)
Here is a better example:
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar
Here you can see that class method is accessed through a class, while instance method is accessed through an instance or object of a class (Foo.new).
Example is copied from here, where you can also find more information on this subject.
Keep in mind: although any code can be put into a class or a instance method, each has it's own use cases and own pros and contras. In OOP we strive for reusable, flexible and readable code, which means that we usually want to put most of the code as structured as instance methods in a sensible domain model.
Just as you said, they are:
"accessed from the class rather than from an object and"
"can have only one running at the same time."
remember, too, that the class is portable
The most important thing is that it keeps your code organized. When you have hundreds of thousands of lines of code, having them all haphazardly throwing stuff around in the same namespace can become a nightmare. Organization is really important, and namespaces are an easy way to get modularity with support from the language.
Somewhat less importantly, class/module methods can share state without leaking it all over the place (e.g. classes can have instance variables), and they can have private support methods to allow for better factoring, while global methods can't effectively be made private.
You have lots of misunderstanding,
In ruby, we can define class and instance method.
Class method is used to do provide processing at class level i.e. data which can only be available at class level or related to all the objects. For example, to count the number of objects belongs to class you need class method. Like
Foo.count
In same way, to process single object you need object method to process a single object like,
obj.save
So, class method is example of singletone design pattern where object can have there own implementation of same method.
RSpec adds a "describe" method do the top-level namespace. However, instead of simply defining the method outside of any classes/modules, they do this:
# code from rspec-core/lib/rspec/core/dsl.rb
module RSpec
module Core
# Adds the `describe` method to the top-level namespace.
module DSL
def describe(*args, &example_group_block)
RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
end
end
end
end
extend RSpec::Core::DSL
Module.send(:include, RSpec::Core::DSL)
What is the benefit of using this technique as opposed to simply defining describe outside any modules and classes? (From what I can tell, the DSL module isn't used anywhere else in rspec-core.)
I made this change a few months ago so that describe is no longer added to every object in the system. If you defined it at the top level:
def describe(*args)
end
...then every object in the system would have a private describe method. RSpec does not own every object in the system and should not be adding describe willy-nilly to every object. We only want the describe method available in two scopes:
describe MyClass do
end
(at the top-level, off of the main object)
module MyModule
describe MyClass do
end
end
(off of any module, so you nest your describes in a module scope)
Putting it in a module makes it easy to extend onto the main object (to add it to only that object, and not every object) and include it in Module (to add it to all modules).
Actually, if that's all there is in the code, I don't really believe it to be much better — if at all. A common argument is that you can easily check that RSpec is responsible for addinng this method in the global namespace by checking the method owner. Somehow it never felt this was needed, as the location of the method already stores that information.
Defining the method outside of any scope would have be equivalent to defining a private instance method in Object:
class Object
private
def double(arg)
arg * 2
end
end
double(3) # OK
3.double(3) # Error: double is private
self.double(3) # Error: double is private
I think privateness is a useful aspect, because it prevents from making certain method calls that have no meaning, that the code shown in the question lacks.
There's an advantge to defining the method in a module, though, but the RSpec code doesn't seem to make use of it: using module_function, not only do you preserve privateness of the instance method, but you also get a public class method. This means that if you have an instance method of the same name, you will still be able to refer to the one defined by the module, by using the class method version.
A common example of module_function is the Kernel module, which contains most function-like core methods like puts (another one is Math). If you're in a class that redefines puts, you can still use Kernel#puts explicitly if you need:
class LikeAnIO
def puts(string)
#output << string
end
def do_work
puts "foo" # inserts "foo" in #output
Kernel.puts "foo" # inserts "foo" in $stdout
end
end
Let's say I have a bunch of related functions that have no persistent state, say various operations in a string differencing package. I can either define them in a class or module (using self) and they can be accessed the exact same way:
class Diff
def self.diff ...
def self.patch ...
end
or
module Diff
def self.diff ...
def self.patch ...
end
I can then do Diff.patch(...). Which is 'better' (or 'correct')?
The main reason I need to group them up is namespace issues, common function names are all used elsewhere.
Edit: Changed example from matrix to diff. Matrix is a terrible example as it does have state and everyone started explaining why it's better to write them as methods rather than answer the actual question. :(
In your two examples, you are not actually defining methods in a Class or a Module; you are defining singleton methods on an object which happens to be a Class or a Module, but could be just about any object. Here's an example with a String:
Diff = "Use me to access really cool methods"
def Diff.patch
# ...
end
You can do any of these and that will work, but the best way to group related methods is in a Module as normal instance methods (i.e. without self.):
module Diff
extend self # This makes the instance methods available to the Diff module itself
def diff ... # no self.
def patch ...
end
Now you can:
use this functionality from within any Class (with include Diff) or from any object (with extend Diff)
an example of this use is the extend self line which makes it possible to call Diff.patch.
even use these methods in the global namespace
For example, in irb:
class Foo
include Diff
end
Foo.new.patch # => calls the patch method
Diff.patch # => also calls Diff.patch
include Diff # => now you can call methods directly:
patch # => also calls the patch method
Note: the extend self will "modify" the Diff module object itself but it won't have any effect on inclusions of the module. Same thing happens for a def self.foo, the foo won't be available to any class including it. In short, only instance methods of Diff are imported with an include (or an extend), not the singleton methods. Only subclassing a class will provide inheritance of both instance and singleton methods.
When you actually want the inclusion of a module to provide both instance methods and singleton methods, it's not completely easy. You have to use the self.included hook:
module Foo
def some_instance_method; end
module ClassMethods
def some_singleton_method; end
end
def self.included(base)
base.send :extend, ClassMethods
end
def self.will_not_be_included_in_any_way; end
end
class Bar
include Foo
end
# Bar has now instance methods:
Bar.new.some_instance_method # => nil
# and singleton methods:
Bar.some_singleton_method # => nil
The main difference between modules and classes is that you can not instantiate a module; you can't do obj = MyModule.new. The assumption of your question is that you don't want to instantiate anything, so I recommend just using a module.
Still you should reconsider your approach: rather than using arrays of arrays or whatever you are doing to represent a Matrix, it would be more elegant to make your own class to represent a matrix, or find a good class that someone else has already written.
Ruby Modules are used to specify behaviour, pieces of related functionality.
Ruby Classes are used to specify both state and behaviour, a singular entity.
There is a maxim in software design that says that code is a liability, so use the less code possible. In the case of Ruby, the difference in code lines is cero. So you can use either way (if you don't need to save state)
If you want to be a purist, then use a Module, since you won't be using the State functionality. But I wouldn't say that using a class is wrong.
As a trivia info: In Ruby a Class is a kind of Module.
http://www.ruby-doc.org/core-1.9.3/Class.html
The following also works
Matrix = Object.new
def Matrix.add ...
def Matrix.equals ...
That's because so-called "class methods" are just methods added to a single object, and it doesn't really matter what that object class is.
As a matter of form, the Module is more correct. You can still create instances of the class, even if it has only class methods. You can think of a module here as a static class of C# or Java. Classes also always have the instance related methods (new, allocate, etc.). Use the Module. Class methods usually have something to do with objects (creating them, manipulating them).
What I'm trying to find out is whether there is some sort of equivalence to what I see in Groovy as ExpandoMetaClasses. I've been reading about Open Classes but I can't quite see what level of scoping Ruby allows of the class modifications.
Borrowing an example from the blog above, in Groovy, I could modify Java's String class and add a method to it like so:
String.metaClass.shout = {->
return delegate.toUpperCase()
}
println "Hello MetaProgramming".shout()
// output
// HELLO METAPROGRAMMING
And I think that Ruby would have you redefine the class and possibly alias it (please help clarify my misunderstandings at this point):
class String
def foo
"foo"
end
end
puts "".foo # prints "foo"
In Groovy, there are ways to scope the redefinition of core Java library methods to single instances or to a group of instances using Categories, which feel similar to what I would define as mixins in Ruby.
What are the ways to scope open classes to specific instances or to subsets of modules?
If I were to install a gem that had redefined some core class, would only that module be affected, or would any .rb file I include that gem with be affected with it?
Apologies in advance for making some possible assumptions on both Ruby and Groovy, I'm new to both but have been trying to find equivalence between the two.
Ruby's classes are never "closed". So when you say:
class String
def omg!
self.replace "OMG"
end
end
You are defining the omg! method on the String class. Unlike in Groovy, which requires the usage of a special metaclass concept, Ruby classes are always open, period.
If you wanted to modify a particular set of Strings, you could do this:
module Magic
def presto
puts "OMG A HAT!"
end
end
class Array
include Magic
end
x = "Hello".extend(Magic)
puts x #=> Hello
x.presto #=> OMG A HAT!
[].presto #=> OMG A HAT!
def x.really?
true
end
x.really? #=> true
Effectively, a module is a collection of methods that can be added to a class or specific instances.
So you can either open a class directly or add new methods to a class using a module. You can also open an instance directly or add new methods to an instance using a module. That's because a class is just an instance of Class ;) Pretty nifty!
In addition to what Yehuda said, instances in Ruby also have metaclasses (technically called "singleton classes"), accessed with class <<whatever. For example, to redo Yehuda's Magic example with a singleton class:
x = "Hello"
class <<x
include Magic
def magical?
true
end
end
x.presto #=> OMG A HAT!
x.magical? #=> true
"Something else".magical? #=> NoMethodError
There's no scoping on modifications to classes. As soon as a class is modified, the modified class is accessible to all later requires and following code.