I understand that when we define a class variable in ruby it's preceded with
##variableName but in this code
class Hello
#var2
##var3=0
def foo1
return #var1
end
def set_foo1(par1)
#var1=par1
end
end
I understand that var3 is a class variable and has to be initialized with some value. But what about var2? Is var2 still corresponds to an object?
When i called the program with obj1.var2=100 i get a noMethodError
Also, when i call puts Hello.var3 i get the same noMethodError
Can anyone please explain where i am getting it wrong?
#var2 is a class level instance variable, whereas ##var3 is a class hierarchy variable.
An article about usage and differences between both of them. The important thing to remember: When you declare a class hierachy variable, it is shared between the class and all descending (inheriting) classes. This is rarely what you want.
Classes are objects just like any other object. Objects can have instance variables. Ergo, classes can have instance variables.
There's really nothing special about that. That's very important to understand in Ruby.
Related
my idea is to create a community wiki for people that come from a java background because reading a lot of explanations, I couldn't comprehend anything until I actually tried a couple of things and the pieces of the puzzle started to find their places. But I first need to make sure I'm getting it right. Coming from such background it was very confusing for me to find out that #variable may mean 2 very different things.
Here is an example:
class Test
#ins = "gah"
def self.ins
puts #ins
end
def initialize()
#ins = "wtf?"
end
def ins2
puts #ins
end
end
As far as I understand, the first #ins is an instance variable of the object representing the class Test. The second #ins is an instance variable in an object of class Test.
Now things start to make some sense to me. Here a couple of examples:
[14] pry(main)> test.ins2
wtf?
We are calling a method of an object and it returns the object's instance variable.
[15] pry(main)> test.ins
NoMethodError: undefined method `ins' for #<Test:0x000000017d9348 #ins="wtf?">
We are trying to call a class method through an object, this method is of the class so we are getting NoMethodError
[16] pry(main)> Test.ins
gah
We are calling a class method so it properly sees the instance variable of the class object.
[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class
We are calling an object method through the class which is incorrect so throwing NoMethodError.
All of the above was performed with ruby 2.0. So what am I asking?
Am I getting it right?
Am I getting the ruby terminology correct?
Any real usage of class instance variables that make sense in a properly designed app? Or are these simply the better ##class variables?
it was very confusing for me to find out that #variable may mean 2 very different things.
No, it doesn't. Classes are objects just like any other object. They can have instance variables just like any other object. They can have instance methods just like any other object. In fact, unlike Java, which has three different kinds of "methods" (instance methods, static methods and constructors), in Ruby, there is exactly one kind of method: instance methods.
The beauty of having classes being objects is precisely that #variable always means exactly the same thing.
There is no such thing as a class instance variable: it's just a normal instance variable like any other. The object happens to be an instance of Class, but that doesn't change the nature of the instance variable. An instance variable of an object of class String is not a string instance variable, it's just an instance variable. Likewise, an instance variable of an object of class Class is just an instance variable.
There is no such thing as a class method: it's just a normal singleton method of an object which happens to be an instance of Class. (Acually, there's no such thing as a singleton method either: it's just a normal instance method of the object's singleton class.)
Note: Rubyists may use the term "class method" in casual conversation. But that doesn't mean that class methods actually exist, it only means that "instance method of the class object's singleton class" is a mouthful. The important thing is: because classes are objects, they work exactly like all other objects. They can have instance methods (defined in class Class or inherited from Module, Object, Kernel or BasicObject), they can have "singleton methods" (which really are instance methods of their respective singleton classes), they can have instance variables.
They can also have class variables (##variables) … those are weird. Ignore them :-)
First, to understand instance variables, one need to know this - classes are objects.
All classes are instances of Class(read the doc) which inherits from Object. That's why classes are objects.
Then, every instance variables(ids marked with #, like #ins) are defined in self.
When self is a class, they are instance variables of classes(class instance variables).
When self is a object, they are instance variables of objects(instance variables).
In different code scopes, the self represents different things.
class Test
# class scope, uncomment following line to see the value of self
# p self
#ins = "gah"
def self.ins
# class scope
# p self
puts #ins
end
def initialize()
# object scope
# p self
#ins = "wtf?"
end
def ins2
# object scope
# p self
puts #ins
end
end
Everything looks right to me.
A class variable will be passed down through inheritance while an instance variable on a class will not. (src: Ruby class instance variable vs. class variable)
As far as design goes, I tend to prefer avoiding class variables altogether (I'd rather use a singleton), but if I had to choose one I would probably choose a class variable over a class instance variable to avoid confusion.
So what I learned is that when I call a variable on an object e.g.
my_object.variable
A method called variable is returning the value of variable
def variable
#variable
end
In Java, there are access modifiers. How can Ruby make use of access modifiers if getter methods are named after their variables?
First, there is a bit of terminology to clean up in the question before answering it.
One is that you never "call" variables. The Ruby expression
my_object.variable
is a method call. There is no such thing as a variable call. You call methods, not variables. Even if the method is named variable. :)
The second is if you did define the method like this
def variable
#variable
end
either directly or by saying
attr_reader :variable
Then you have a method named variable and a variable named #variable.
Now to answer the question.
Ruby places access modifiers public, protected, and private on methods only, and not on variables. Access controls on variables don't really make sense, because they only be referenced within an object’s methods, and never with a prefix! In other words, you can never write this:
obj.#var
That's just a syntax error. You can write
obj.var
where var is the name of a method. And the access controls apply to that method only.
The fact that you may be making variables and methods with the same name (except for the #) actually doesn't matter. Only methods have access controls.
Hope that helps clear up some understandable confusion!
There are several ways to make a method private in Ruby.
Use private to make all later methods private:
class Foo
def public_method
end
private
def private_method
end
end
Or make a method private after you defined it:
class Foo
def public_method
end
private :public_method # public_method is now private
end
Or - since the method definition returns a symbol too - this also works:
class Foo
private def method_name
end
end
Suppose I have the following:
module MyModule
module SubModule
Var = 'this is a constant'
var = 'this is not a constant'
def hello_world
return 'hello world!'
end
end
end
In the same file, I can only seem to access MyModule::SubModule::Var, but not any the constant or the method. If I now create a class and include these modules in different ways, I get additional strange behavior:
class MyClass
include MyModule
def initialize()
puts SubModule::Var
end
def self.cool_method
puts SubModule::Var
end
end
In this case, I can again only access Var, but not the other two. SubModule::var and SubModule::hello_world do not work. Finally:
class MyClass
include MyModule::SubModule
def initialize()
puts Var
puts hello_world
end
def self.cool_method
puts Var
puts hello_world
end
end
In this case, I can now access both Var and the method hello_world but not var, and, the weirdest thing, is that hello_world appears to have become an instance method! That is, the call to hello_world in initialize works, but the one in self.cool_method doesn't. This is pretty strange, considering that Var seems to have been included as a class variable, since outside the class, I must access them like so:
MyClass::Var
x = MyClass.new
x.hello_world
So, I have a few major questions.
What is going on behind the scenes with regards to Var vs var? It appears that capitalizing a variable name is more than just a convention after all.
When includeing a module, what kinds of things are passed to the including class, and at what scope?
Is there a way to do the opposite? That is, use include to include an instance variable or a class method?
What is going on behind the scenes with regards to Var vs var? It appears that capitalizing a variable name is more than just a convention after all.
Yes, of course, it's not a convention. Variables which start with an uppercase letter are constants, variables which start with a lowercase letter are local variables. The two are completely different.
When includeing a module, what kinds of things are passed to the including class, and at what scope?
Nothing gets passed anywhere. includeing a mixin simply makes that mixin the superclass of the class you are includeing it into. That's all. Everything else then works exactly as with classes.
Is there a way to do the opposite? That is, use include to include an instance variable or a class method?
I don't understand this question. Instance variables have nothing to do with mixins or classes. They belong to instances, that's why they are called "instance" variables.
There are no such things as "class methods" in Ruby. Ruby only knows one kind of methods: instance methods. When Rubyists talk to each other, they will sometimes use the term "class method" to mean "singleton method of an object that happens to be a class", but they do that knowing full well that class methods don't actually exist, it's just a shorthand in conversation. (And, of course, singleton methods don't exist either, they are just a convenient way of saying "instance method of the singleton class".)
my idea is to create a community wiki for people that come from a java background because reading a lot of explanations, I couldn't comprehend anything until I actually tried a couple of things and the pieces of the puzzle started to find their places. But I first need to make sure I'm getting it right. Coming from such background it was very confusing for me to find out that #variable may mean 2 very different things.
Here is an example:
class Test
#ins = "gah"
def self.ins
puts #ins
end
def initialize()
#ins = "wtf?"
end
def ins2
puts #ins
end
end
As far as I understand, the first #ins is an instance variable of the object representing the class Test. The second #ins is an instance variable in an object of class Test.
Now things start to make some sense to me. Here a couple of examples:
[14] pry(main)> test.ins2
wtf?
We are calling a method of an object and it returns the object's instance variable.
[15] pry(main)> test.ins
NoMethodError: undefined method `ins' for #<Test:0x000000017d9348 #ins="wtf?">
We are trying to call a class method through an object, this method is of the class so we are getting NoMethodError
[16] pry(main)> Test.ins
gah
We are calling a class method so it properly sees the instance variable of the class object.
[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class
We are calling an object method through the class which is incorrect so throwing NoMethodError.
All of the above was performed with ruby 2.0. So what am I asking?
Am I getting it right?
Am I getting the ruby terminology correct?
Any real usage of class instance variables that make sense in a properly designed app? Or are these simply the better ##class variables?
it was very confusing for me to find out that #variable may mean 2 very different things.
No, it doesn't. Classes are objects just like any other object. They can have instance variables just like any other object. They can have instance methods just like any other object. In fact, unlike Java, which has three different kinds of "methods" (instance methods, static methods and constructors), in Ruby, there is exactly one kind of method: instance methods.
The beauty of having classes being objects is precisely that #variable always means exactly the same thing.
There is no such thing as a class instance variable: it's just a normal instance variable like any other. The object happens to be an instance of Class, but that doesn't change the nature of the instance variable. An instance variable of an object of class String is not a string instance variable, it's just an instance variable. Likewise, an instance variable of an object of class Class is just an instance variable.
There is no such thing as a class method: it's just a normal singleton method of an object which happens to be an instance of Class. (Acually, there's no such thing as a singleton method either: it's just a normal instance method of the object's singleton class.)
Note: Rubyists may use the term "class method" in casual conversation. But that doesn't mean that class methods actually exist, it only means that "instance method of the class object's singleton class" is a mouthful. The important thing is: because classes are objects, they work exactly like all other objects. They can have instance methods (defined in class Class or inherited from Module, Object, Kernel or BasicObject), they can have "singleton methods" (which really are instance methods of their respective singleton classes), they can have instance variables.
They can also have class variables (##variables) … those are weird. Ignore them :-)
First, to understand instance variables, one need to know this - classes are objects.
All classes are instances of Class(read the doc) which inherits from Object. That's why classes are objects.
Then, every instance variables(ids marked with #, like #ins) are defined in self.
When self is a class, they are instance variables of classes(class instance variables).
When self is a object, they are instance variables of objects(instance variables).
In different code scopes, the self represents different things.
class Test
# class scope, uncomment following line to see the value of self
# p self
#ins = "gah"
def self.ins
# class scope
# p self
puts #ins
end
def initialize()
# object scope
# p self
#ins = "wtf?"
end
def ins2
# object scope
# p self
puts #ins
end
end
Everything looks right to me.
A class variable will be passed down through inheritance while an instance variable on a class will not. (src: Ruby class instance variable vs. class variable)
As far as design goes, I tend to prefer avoiding class variables altogether (I'd rather use a singleton), but if I had to choose one I would probably choose a class variable over a class instance variable to avoid confusion.
This question already has answers here:
What does a Java static method look like in Ruby?
(2 answers)
Closed 8 years ago.
I'm trying to define a method called function. It works when I do this:
a = A.new
def a.function
puts 100
end
But I want the method to work for any instance variable, not just a. For example, when I call function on an instance of A other than a, nothing happens. So I used A::f to define the function rather than a.function.
class A
attr_accessor :function
attr_accessor :var
end
def A::function
self.var = 0x123
end
a = A.new
a.function
puts a.var
This compiles fine but when I try to call the function I get an error. Why is it not working and how can I do what I'm attempting?
You're really tangled up here. I suggest you check out _why's poignant guide to ruby and get a handle on what is going on here.
As an attempt to steer you right, though…
a isn't an instance variable. It's a local variable that you're using to reference an instance of A.
def a.foo defines a method on the eigenclass of a.
attr_accessor :function already defined A#function (that is, an instance method on A called function) that essentially looks like this: def function; #function; end
def A::function defines a class method on A that you could access via A.function (not an instance of A as in a.function.
MRI doesn't really compile ruby like you might anticipate. It runs it, dynamically interpreting statements in realtime.
You probably want to stick with defining standard instance methods in the traditional manner, and avoid using “function” as a placeholder name since it is a reserved word and has special meaning in other languages. I'll use “foo” here:
class A
def foo
'Awww foo.'
end
end
That's it, you can now create an instance of A (a = A.new) and call foo on it (a.foo) and you'll get back 'Aww foo.'.
class A
def function
puts 100
end
end
a = A.new
a.function #=> "100"
That's a classic instance method. Is that what you're looking for or am I missing something?
If you're trying to define methods dynamically, you could use Class#define_method. Otherwise, if you are just wanting to define the method for the class, defining it in the scope of class A will suffice.
Anyway, could you be more specific on what are you trying to accomplish and what kind of error you're having, please?