In the following code, puts ParentObjectC2 is not working. I was referring to an online tutorial.
class BaseParentClass
def method
100
end
end
class Child1 < BaseParentClass
puts "I am child class one , I inherit the properties of BaseParentClass"
ParentObjectC1=BaseParentClass.new
puts ParentObjectC1.method
end
class Child2 < BaseParentClass
puts "I am child two, I also inherit the properties of BaseParentClass"
ParentObjectC2=BaseParentClass.new
puts ParentObjectC2
end
My output
ragesh#ragesh:~/Ruby/HelloWorld$ ruby classDemo.rb
I am child class one , I inherit the properties of BaseParentClass
100
I am child two, I also inherit the properties of BaseParentClass
#<BaseParentClass:0x00000001423bb8>
Add a to_s method to the base class if you want to print in sensibly. In the first subclass, you print the method function. In the second, you try to print the object itself.
And please, use lowercase object names. Uppercase just looks like a class
def to_s
"base #{method}"
end
One more thing. You can call the method directly. Do not create a base object and call it on the base. This does not illustrate inheritance at all!
Instead just call:
puts method
Related
How can one get the class a method was defined in?
I've found how to look up descendents and ansestors: Look up all descendants of a class in Ruby
But that doesn't necessarily get me the defining class (last defining class really).
I've found how to get the calling class:
Ruby Inheritance Get Caller Class Name
But I want the opposite. I would like how to get the defining class.
I've also tried Module.nesting. That gets me what I want in this case, but I worry it will be inconsistent and not acceptable in a larger codebase of which I don't have ultimate control.
puts RUBY_VERSION
# Test class vs super.
class Super
def test_func
puts "#{self.class}, #{ __method__}"
end
end
class Child < Super
def test_func2
self.test_func
end
end
Child.new.test_func
I had hoped for:
1.8.7
Super, test_func
But got:
1.8.7
Child, test_func
You asked self.class of Child object and you got it.
You need use Method#owner to return the class or module that defines the method.
class Super
def test_func
puts "#{method(__method__).owner}, #{ __method__}"
end
end
class Child < Super
def test_func2
self.test_func
end
end
Child.new.test_func
# will print: Super, test_func
or just
Child.new.method(:test_func).owner
#=> Super
I wish to create a way to make Children classes express some business definitions on Class Level.
I tried to use Class Variables for that, but i found that they share state between all Classes, so once i define the Second Class, the "##attribute" class var changes its value for all adjacent Class instances.
class Parent
def self.type(value)
##_type = value
end
def render
puts ##_type
end
end
class Children < Parent
type "name"
end
Children.new.render # Result: name. Expected: name
class Children2 < Parent
type "title"
end
Children2.new.render # Result: title. Expected: title
Children.new.render # Result: title. Expected: name
How can i create this DSLs in the most simple and direct way?
This is a common pattern for several Ruby Gems, like HTTParty, Virtus, and etc.
I even tried to look at their source code to understand how its done, but it seems too much complex for what i want.
Thanks for your help!
Class variables are one of a triumvirate of Ruby tools that most experienced Rubiests rarely, if ever, use.1. Instead you want to use a class-level instance variable, Parent being an instance of the class Class.
class Parent
def self.type=(value)
#type = value
end
def self.type
#type
end
def render
puts self.class.type
end
end
class Children < Parent
self.type = "name"
end
Children.new.render
#=> "name"
class Children2 < Parent
self.type = "title"
end
Children2.new.render
#=> "title"
Children.new.render
#=> "name"
Firstly, the class method type= is called a "setter" and the class method "type" is called a "getter". You had a setter type, taking an argument. If you do that, how will you just get its value? To use it as a getter as well you'd have to do something like the following:
def self.type=(value=nil)
if value.nil?
#type
else
#type = value
end
end
Here it would make more sense to just define a getter
def self.type
#type
end
and having no setter, just writing, for example, #type = "name".
That is kludgy and only works if you don's want to set #type to nil. You could also leave your method as a setter and use self.class.instance_variable_get(:#type) to get its value, but that's equally awful. It's best to have a setter and a getter.
When using the setter we need to preface type with self. to tell Ruby we wish to invoked the getter and not set a local variable type to a given value. Of course we could instead just write, for example, `#type = "title".
The conventional way to create a setter and a getter is to write attr_accessor :type (invoking the class method Module#attr_accessor). As class methods are stored in a class' singleton class, that could be done as follows2:
class Parent
class << self
attr_accessor :type
end
def render
puts self.class.type
end
end
class Children < Parent
self.type = "name"
end
Children.new.render
#=> "name"
class Children2 < Parent
self.type = "title"
end
Now consider the instance method Parent#render. Being an instance method its receiver is an instance of the class (or a subclass), say parent = Parent.new. That means that when render is invoked within the method self equals parent. We want to invoke the class method type, however. We must therefore convert parent to Parent, which we do with self.class.
1. The other two (in my opinion, of course) are global variables and for loops. Their popularity among Ruby newbies is probably due to the fact that they tend to make their debut in Chapter 1 of many learning-Ruby books.
2. There are many ways to define attr_accessor in Parent's singleton class. Two others are singleton_class.instance_eval do { attr_accessor :type } and singleton_class.send(:attr_accessor, :type).
Ok, i have no idea why it worked, but it worked this way:
class Parent
class << self
attr_accessor :_type
def type(value)
self._type = value
end
end
def render
puts self.class._type
end
end
I really wish to understand why, but "self.class", and "class << self" seems a lot of dark to me.
Light?
I have a class:
Class Temp
def Temperature
puts "It's hot"
end
end
I can call an instance of that:
mytemp = Temp.new
I can call the method Temperature on it. How do I know if I am calling an instance class or class methods?
Lets define following class. I defined methods beginning with lowercase as everybody does.
class Temp
def temperature
puts "I am instance"
end
def self.temperature
puts "I am class"
end
end
t = Temp.new
t.temperature
-> "I am instance"
Temp.temperature
-> "I am class"
t = Temp.new
t.class.temperature
-> "I am class"
Hope it helps and makes things clear :)
Since you need to call .new to instantiate the class, Temperature is an instance method. You define class methods by appending a self to the method name - def self.Temperature. Then you'd call it without instantiating the class: Temp.Temperature.
My goal is:
class Bermuda
class << self
def grass
puts self.superclass.name
end
end
end
# my goal is that this expression
Bermuda.grass
# will output a string of the class name it resides in
=> "Bermuda"
I cannot display the name of the class that holds a singleton method. I have tried a number of different stabs and standard library searches but haven't found an answer.
This is partially pointless because you would not need a class method to display the information that you would need in the first place to call that method. I'm curious if it's possible or I'm completely missing the scope.
Just call name on self
class Bermuda
class << self
def grass
puts self.name
end
end
end
This sort of an implementation isn't recommended since all you have to do to get the class name is call Bermuda.name
Please see the answer given below by #MatthewCliatt for more info.
It's as simple as:
self.class.name
But, the catch is that this isn't for class methods, it's for instance methods.
That means you don't declare it with self. This was your code:
class Bermuda
class << self
def grass
puts self.superclass.name
end
end
end
And that will make the grass method a class method. You would have to call it like Bermuda.grass.
But, if you can call class methods like the one above, you could just as easily write: Bermuda.name.
I'm assuming you can't call class methods, probably because you're working with an instance. So you want to write this method as such:
class Bermuda
def grass
puts self.class.name
end
end
You say you're creating a singleton method, but I don't think your method is a singleton method in the usual sense (i.e. a method on an object that is an instance of a class, but not itself a class).
I believe the class << self notation you use merely results in a class method being defined, identical to:
def self.grass
puts name
end
In irb:
2.3.0 :003 > class Bermuda; def self.grass; puts name; end; end
=> :grass
2.3.0 :004 > Bermuda.grass
Bermuda
I have the following Ruby namespace problem:
I have a number of top-level methods in a "library", among these I have a get_name(param) method.
The problem is that I want to use this get_name(param) method inside a class that has its own get_name() method (without param!).
Of course this results in a problem as the 2 methods are different and the new one in the class overrides the top-level one.
Is there a way to do something like this:
def get_name(param)
puts param
end
class Foo
def get_name()
puts "name"
end
def bar()
self.get_name() #should work and print name, i.e. it uses the get_name method of Foo
get_name("abc") #should work and print abc, i.e. it uses the top-level method
end
end
I would like to know if there is an easy way to achieve this without having to alter the name or scope of the top-level methods. (The goal is to have those available without modification as global methods, but still be able to call instance methods of Foo without errors.
If the library methods are really top-level methods and are not part of any class or module, then, they will get defined as private methods of Object class.
You can do following to invoke it:
def bar()
self.get_name()
Object.send(:get_name, "abc") # Will print "abc" to console
end
The so called "top level method" is only a method of main object, which is only an Object. If you want that method to be able to be called (almost) anywhere, you should make it a kernel method.
module Kernel
def get_name(param)
puts param
end
end
Note that Kernel is almost at the tail of any classes ancestors chain (before BasicObject), which means almost all the objects are a Kernel. So in your Foo class, you can override it like this:
class Foo
def get_name(*args)
return super if args.any?
puts 'name'
end
end
Edit
If you can't make those top level methods kernel methods, you can store the main object in a constant or a global variable, and call those top level methods on it.
$main = self
class Foo
def get_name(*args)
return $main.send(:get_name, *args) if args.any?
puts 'name'
end
end
First off: there is no such thing as a "top-level method". There is exactly one kind of method in Ruby: instance methods.
The method you are referring to is a private instance method of Object. Since Object is a superclass of almost any other class (excluding Object and its superclasses), if you are sure that there are no other methods with the same name somewhere else in the inheritance hierarchy, you could use Method#super_method to get access to the method and then call it:
def get_name(param)
puts param
end
class Foo
def get_name
puts 'name'
end
def bar
get_name #should work and print name, i.e. it uses the get_name method of Foo
method(:get_name).super_method.('abc') #should work and print abc, i.e. it uses the top-level method
end
end
Foo.new.bar
# name
# abc
Alternatively, if you don't know whether there are any other methods by the same name within the inheritance hierarchy, you could grab a reference to the UnboundMethod directly from Object and then bind and call it:
class Foo
def bar
get_name #should work and print name, i.e. it uses the get_name method of Foo
Object.instance_method(:get_name).bind(self).('abc') #should work and print abc, i.e. it uses the top-level method
end
end
Foo.new.bar
# name
# abc