Simple question:
In java you can define :
void myFunction<T>(T value) { //do stuff }
Is there an equivalent in ruby, and if not, how can I achieve a similar result (passing class types?)
You can pass a class to a method just like passing normal objects. For example
def create_object(klass, *args)
klass.new(*args)
end
create_object(String) #=> ""
create_object(Hash) #=> {}
create_object(Array, 3, :hello) #=> [:hello, :hello, :hello]
First a few definitions
Generics is an abstraction over types
Polymorphism is a sum-type pattern
Composition is a product-type pattern
Most OO languages lean towards polymorphism
Ruby is an OO language. Polymorphism is at the core of its design. The type system in Ruby is only getting strong in Ruby 3. So we may see more interesting generics at that point; but until now, I haven't heard that to be a feature.
To achieve this, we technically need to figure out a way of applying a method on separate types without knowing the type. It's a lot of code duplication is possible.
Your Java example…
void myFunction<T>(T value) { //do stuff }
…can be translated into Ruby as
def myFunction(value)
raise "Only works with T types" unless value.is_a? T
# do stuff
end
Where the magic now has to happen is in defining the possible set of T. I'm thinking something like…
class T
def _required_for_MyFunction()
raise "T is abstract!"
end
end
class Something < T
def _required_for_MyFunction()
# does something
end
end
class Nothing < T
def _required_for_MyFunction()
# does nothing
end
end
The painful part of polymorphism is that you have to define your type space from the get-go. The good parts of this is you have total control of the domain space.
Ruby follows duck typing. You can pass arguments of any class to any method (which is the original reason why you might need generics). If you want to get the class of said argument, you can still use #class
def foo(bar)
bar.class
end
foo 'baz' # => String
foo 42 # => Fixnum
Related
I want to designate some strings that won't change in a Ruby class. When should I use a constant vs a method?
class ApiWrapper
# option 1
PATH = "/posts"
# option 2
def self.path
"/posts"
end
def get_posts
Net::HTTP.get('blogpostworld.com', ApiWrapper::PATH)
# vs
Net::HTTP.get('blogpostworld.com', ApiWrapper.path)
end
end
Accessing these is the difference between ApiWrapper::PATH vs ApiWrapper.path
Usage would look like:
wrapper = ApiWrapper.new(config)
response = wrapper.get_posts
When would I favor one option over the other?
Personally I like the method option, especially if it is declared as private:
class ApiWrapper
# ... initializer stuff
def get_posts
Net::HTTP.get('blogpostworld.com', ApiWrapper.path)
end
private_class_method def self.path
"/posts"
end
end
I don't have a definitive answer, but consider:
ApiWrapper::PATH << "1"
p ApiWrapper::PATH
#=> "/posts1"
ApiWrapper.path << "1"
p ApiWrapper.path
#=> "/posts"
Unless you freeze the Constant:
class ApiWrapper
PATH = "/posts".freeze
end
ApiWrapper::PATH << "1"
#=> can't modify frozen String (FrozenError)
And ApiWrapper::PATH looks like a constant, ApiWrapper.path doesn't.
Here some thoughts from my experience.
Method approach:
When using a template method pattern.
When you want to keep that constant private and you don't use private_constant explicitly (docs). This can be helpful to prevent coupling from other modules.
When the value is expected to change at some point in the future but you don't want to modify the signature of the method (thinking of a gem).
Constant approach:
When you want to make the value public (can also be achieved with a public class method).
When you want to make explicit that the value is going to remain the same through the execution (as #iGian mentioned in his answer).
However, in most of the cases I would say it's OK using any of the approaches and switch to one of them if needed.
I'm not sure where I have seen this, or if I just think I have seen it, but I would like to be able to call a method that creates an instance of a class with the same name. So, instead of:
# The class is called 'Vector3', for example:
Vector3.new(x,y,z)
I would like to have an eponymous method that instantiates the class, like so:
Vector3(x,y,z) #<- returns instance of Vector3 class
How would you define that in Ruby?
As #Eli mentioned, you can define a method in the kernel:
def Kernel.Vector3(*args)
Vector3.new(*args)
end
Ruby does this for Array, Complex, Float, Hash, Integer, Rational and String where you probably saw it.
The reason it works is that Object includes Kernel, hence all objects in your program (except ones directly inheriting from BasicObject) will have that method.
However, doing so is unidiomatic, unnecessary (you clutter all objects with an additional method), confusing (capitalized identifiers should be constants) and generally looked down upon.
AFAIK you can't. You can do something similar, Vector3[x, y, z].
class Vector3
def initialize(x, y, z)
# ...
end
def self.[](*args)
self.new(*args)
end
end
Note that the Ruby library uses this device as well. There's Hash.new(...) and Hash[...] , but no Hash(...). This parallels how Proc objects are invoked:
greet = Proc.new { |name| puts "Hello, #{name}" }
greet["Amadan"]
EDIT: I stand corrected:
module Kernel
def Vector3(*args)
Vector3.new(*args)
end
end
But, as Eli Sadoff said, it is impractical, violates encapsulation, and Ruby style (functions and methods should be lowercase).
This answers what I understood the question to be from the title. (Somehow I overlooked the example that contradicts that.) I will leave my answer because I think it includes some interesting elements.
class MyClass
def hi
"hi"
end
my_alias = to_s
singleton_class.class_eval { alias_method(my_alias, :new) }
end
MyClass.methods(false)
#=> [:MyClass]
my_instance = MyClass.MyClass
#=> #<MyClass:0x007fadc2092320>
my_instance.hi
#=> "hi"
Note that this works when the alias of new is passed arguments and/or a block.
See Object#singleton_class and Module#class_eval.
I am working with data structures fundamentals in Ruby for learning at the CS sophomore/junior level.
My question: Given the following code, does anyone see any design issues with this approach to a data structures library in Ruby? Especially the Module#abstract_method. Is it okay to do this in terms of duck typing philosophy? Does this make the code clearer for people from static languages and give some semblance of an interface?
class Module
def abstract_method(symbol)
module_eval <<-"end_eval"
def #{symbol.id2name}(*args)
raise MethodNotImplementedError
end
end_eval
end
end
class AbstractObject < Object
abstract_method :compare_to
protected :compare_to
class MethodNotImplementedError < StandardError; end
def initialize
super
end
include Comparable
def <=>(other)
if is_a?(other.class)
return compare_to(other)
elsif other.is_a?(self.class)
return -other.compare_to(self)
else
return self.class <=> other.class
end
end
end
# methods for insertion/deletion should be provided by concrete implementations as this behavior
# is unique to the type of data structure. Also, concrete classes should override purge to discard
# all the contents of the container
class Container < AbstractObject
include Enumerable
def initialize
super
#count = 0
end
attr_reader :count
alias :size :count
# should return an iterator
abstract_method :iter
# depends on iterator object returned from iter method
# layer of abstraction for how to iterate a structure
def each
i = iter
while i.more?
yield i.succ
end
end
# a visitor provides another layer of abstraction for additional
# extensible and re-usable traversal operations
def accept(visitor)
raise ArgumentError, "Argument must be a visitor" unless visitor.is_a?(Visitor)
each do |obj|
break if visitor.done?
visitor.visit(obj)
end
end
# expected to over-ride this in derived classes to clear container
def purge
#count = 0
end
def empty?
count == 0
end
def full?
false
end
def to_s
s = ""
each do |obj|
s << ", " if not s.empty?
s << obj.to_s
end
self.class + "{" + s + "}"
end
end
class List < Container
def initialize
super
end
def compare_to(obj)
"fix me"
end
end
A few remarks:
Defining a method that only raises a NotImplemented error is somewhat redundant, since Ruby will do that anyway if the method does not exist. The code you wrote there is just as useful as simply putting a comment to say "You must implement a method called compare_to". In fact that is what the Enumerable module in Ruby's standard library does - in the documentation it specifically says that in order to use the functionality in Enumerable you must define an each() method.
a compare_to method is also redundant, since that is precisely what the <=> operator is for.
Using an actual iterator object is a bit overkill in Ruby, since blocks tend to have a much more elegant and simple approach. Same goes for your visitor pattern - you don't need to use a visitor for "extensible and re-usable traversal operations" when you can just pass a block to a traverse method. For example you have many of them in Enumerable: each, each_with_index, map, inject, select, delete_if, partition, etc. All of these use a block in a different way to provide a different type of functionality, and other functionality can be added on in a fairly simple and consistent way (especially when you have open classes).
Regarding interfaces, in Ruby (and pretty much any other dynamic language, like Python) people usually use interfaces that are implicit, which means that you don't actually define the interface in code. Instead you typically rely on documentation and proper testing suites to ensure that code works well together.
I think that your code may be more coherent to someone coming from a Java world because it sticks to the "Java way" of doing things. However to other Ruby programmers your code would be confusing and difficult to work with since it doesn't really stick to the "Ruby way" of doing things. For example, an implementation of a select function using an iterator object:
it = my_list.iter
results = []
while it.has_next?
obj = it.next
results << obj if some_condition?
end
is much less clear to a Ruby programmer than:
results = my_list.select do |obj|
some_condition?
end
If you would like to see an example of a data structures library in Ruby, you can see the algorithms gem here: http://rubydoc.info/gems/algorithms/0.3.0/frames
Also take a look at what is provided by default in the Enumerable module: http://www.ruby-doc.org/core/classes/Enumerable.html. When you include Enumerable you receive all of these functions for free.
I hope this helps!
Learning ruby. I'm under the impression that boolean attributes should be named as follows:
my_boolean_attribute?
However, I get syntax errors when attempting to do the following:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
Apparently ruby is hating the "?". Is this the convention? What am I doing wrong?
Edit: three-years later; the times, they are a-changin'…
Julik's answer is the simplest and best way to tackle the problem these days:
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
My answer to the original question follows, for posterity…
The short version:
You can't use a question mark in the name of an instance variable.
The longer version:
Take, for example, attr_accessor :foo — it's simply conceptually a bit of syntactic sugar for the following:
def foo
#foo
end
def foo=(newfoo)
#foo = newfoo
end
Furthermore, the question-mark suffix is mostly just a convention to indicate that the return value of a method is a boolean.
The best approximation I can make of what you're going for here…
class MyClass
def initialize
#awesome = true
end
def awesome?
#awesome
end
end
In this case, there may be a case to be made for using attr_accessor — after all, it may be explicit that you're working directly with a boolean attribute. Generally, I save the question-mark suffix for when I am implementing a method whose boolean return value is based on slightly more complex conditions than just the value of an attribute.
Cheers!
Edit, two years later, after a recent comment:
Ruby enforces certain naming conventions. Symbols in Ruby can't have question marks. Thus invocations of :my_boolean_attribute? both will fail with a NameError. Edit: not correct, just use the quoted syntax for a symbol, e.g., :"my_attribute?"
Symbols are immutable, attempting to assign to one will throw a SyntaxError.
The easiest way to quickly add a "question method" is to use aliasing for your reader method
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
The attr_accessor symbol implies that the variable name is #my_boolean_attribute, so that's what you should be setting (not the symbol).
Also, you can't use ? for variables, just method names.
? is convention for methodnames, not variables. You can't use an instance variable named #foo?, however you could use a variable named #foo and name the (manually created) getter method foo? if you wanted to.
Monkey-patching metaprogramming - maybe it can be made more elegant, this is only a quick draft, and I haven't done metaprogramming for a little while...
# inject the convenience method into the definition of the Object class
class Object
def Object::bool_attr(attrname)
class_eval { define_method(attrname.to_s,
lambda { instance_variable_get('#' + attrname.to_s.chop) }) }
class_eval { define_method(attrname.to_s.chop+"=",
lambda { |x| instance_variable_set('#'+attrname.to_s.chop, x) }) }
end
end
### somewhere later
class MyClass
bool_attr :my_boolean_attribute?
def initialize
#my_boolean_attribute = true
end
end
# yet even more later
foo = MyClass.new
bar = MyClass.new
foo.my_boolean_attribute = 1
puts foo.my_boolean_attribute?
puts bar.my_boolean_attribute?
With this approach, you can be DRY and get the nice questionmark too. You just might need to pick a better name than "bool_attr", like, "bool_attr_accessor" or something similar.
The definitions that I made are a bit cranky, in a sense that the question mark is present in the original symbol. Probably a cleaner approach would be to avoid the questionmark in the symbol name and append it during the definition of the method - should be less confusing.
Oh, and almost forgot to include the obligatory link: Seeing metaclasses clearly
I looked through the answers, and while the accepted answer is on-target, it introduces "extra" noise in the class. The way I'd suggest solving this issue is:
class Animal
attr_writer :can_swim
def initialize(animal_type_name)
#can_swim = true
#animal_type_name = animal_type_name
end
def can_swim?
#can_swim
end
def to_s
#animal_type_name
end
end
dog = Animal.new('Dog in a bag')
dog.can_swim = false
puts "Can this #{dog} Swim? --- [#{dog_without_legs.can_swim? ? 'YEP!' : 'NOPE!'}]"
I got a Base superclass and a bunch of derived classes, like Base::Number, Base::Color. I'd like to be able to use those child classes as if I they inherited from say Fixnum in the case of Number.
What's the best way to do this, while still having them respond appropriately to is_a? Base ?
So, I should be able to do
Number.new(5) + Number.new(6) # => 11
Number.new.is_a? Base # => true
I'm thinking I could mix-in Base, and overwrite the is_a?, kind_of? and instance_of? methods, but hopefully there's a cleaner way.
This is actually quite simple using Ruby:
module Slugish
attr_accessor :slug
def loud_slug
"#{slug}!"
end
end
class Stringy < String
include Slugish
end
class Hashy < Hash
include Slugish
end
hello = Stringy.new("Hello")
world = Stringy.new("World")
hello.slug = "So slow"
world.slug = "Worldly"
hello.loud_slug #=> "So slow!"
world.loud_slug #=> "Worldly!"
hello.is_a?(Slugish) #=> true
world.is_a?(Slugish) #=> true
"#{hello} #{world}" #=> "Hello World"
stuff = Hashy.new
stuff[:hello] = :world
stuff.slug = "My stuff"
stuff.loud_stug #=> "My stuff!"
stuff.is_a?(Slugish) #=> true
Why do you insist on using is_a?/kind_of? when respond_to? is a much cleaner way of checking things? You want objects to implement an interface/contract not to be a subclass of any arbitrarily chosen superclass. But maybe I'm missing some kind of requirement here.
Edit: I understand your reasoning, but it often leads to poor OO/dynamic design. Either you're doing something like this, which might be an acceptable idea in leaf classes but in a framework should be solved with inheritance:
if a.is_a?(something)
#do something
elif a.is_a?(something_else)
#do something else
...
or something like this:
if !a.is_a?(something)
#raise condition/return null/etc.
endif
...
I think that letting code fail with does not understand exception in message passing based language is a perfect design decision.
As an added problem, using is_a? instead of respond_to? limits your ability to use mock-up objects while unit testing. Which can be quite a big issue even for moderately complicated code.
I think you are using inheritance incorrectly if you have completely unrelated classes like "Number" and "Color" all deriving from the same base class. I would use composition instead if they do need access to the same routines (not sure why they would though).
Ruby's equivalent to multiple inheritance is mixins. It sounds to me like what you want is for Base to be a module that gets mixed in to several classes.