In Boo, let's say I'm overriding a method that takes a parameter that takes string[] urls. Type inference, for whatever reason, isn't matching up to the base class, so I need to explicitly specify the type of the parameter.
class MyClass: MyBase
override method(urls as Array[of (string)])
dostuff()
This turns out not to be correct Boo syntax. What's the right way of specifying that I'm overriding a method that takes an array parameter?
Normally I prefer to expect an IEnumerable, but I'm overriding someone else's base class, which is part of Rhino.DSL.
Edited to add: It turns out my issue was only tangentially related to the array declaration syntax... my real problem was two different versions of the Boo Assembly being referenced in my project.
Parenthesis around a type represents an array of that type:
class MyClass : MyBase
override def method(urls as (string)):
dostuff()
Related
I have a method that returns an object which could be one of many different types of object but which are all part of the same ancestor class. The precise object type is inferred dynamically.
However, I'm confused as to what to put for the return value in the signature. I've put a placeholder below using instance_of to illustrate the problem:
sig{params(instance_class: String).returns(instance_of ParentClass)}
def build_instance instance_class
klass = Object.const_get(instance_class)
return klass.new
end
Given that I don't know which precise class will be returned (and I'd prefer not to list them explicitly) but I do know that it will be a subclass of ParentClass is there a way in Sorbet to specify this? I could use T.untyped but it's unnecessarily loose.
Through trial and error I've discovered that checking that the object includes the type in its ancestors is, if I understand correctly, sorbet's default behaviour.
Sorbet won't check that the object precisely matches the specified Type, only that it includes that type in its ancestors (perhaps this is what Typechecking in general means but I'm fairly new to the game).
To avoid the following error though:
Returning value that does not conform to method result type https://srb.help/7005
you also need to T.cast() the object that you return to the ParentClass:
sig{params(instance_class: String).returns(ParentClass)}
def build_instance instance_class
klass = Object.const_get(instance_class)
# NB instance is a descendent of ParentClass, not an instance...
return T.cast(klass.new, ParentClass)
end
This seems to work but I'd love to know whether it's the correct way to solve the problem.
Is it possible to use prepend for instantiated classes at run time?
Like for example, I need prepend specific class based of value of passed params to initialize method..
ex (if prepend is allowed to be called in initialize) :
def initialize(param)
prepend TestB if param == 2
prepend TestC if param == 3
end
but of course, this will lead into error:
NoMethodError: undefined method `prepend' for .. etc
How would I achieve this? I need to override some methods in a clean way, while instantiating the same class.
prepend is a method belonging to Module, so it cannot be invoked on instances of a class (which is where you are inside the initialize method). If you want to, you could use extend (a method belonging to Object) to mix in different method implementations into the instance of your class.
Personally I would consider this to be a kind of Control Couple and rather try and avoid it. Depending on your concrete situation, a factory or adapter pattern might be more appropriate.
When sent a message, a Ruby object searches to see whether it has a method by that name to respond with. Its method lookup searches in the following order, and uses the first method it finds.
Singleton methods defined on itself (aka methods on its "eigenclass")
Methods defined in its class
Any modules mixed into its class, in reverse order of inclusion (only the earliest inclusion of a given module has any effect - if the superclass includes module A, and the subclass includes it again, it’s ignored in the subclass; if the subclass includes A then B then A, the second A is ignored) (update: note that this was written before Module.prepend existed)
Its parent class
Any methods mixed into the parent class, the parent's parent, etc.
Or, to put it more simply, it looks on itself, then everything in self.class.ancestors in the order they're listed.
This lookup path is followed at the moment the method is called; if you make an instance of a class, then reopen the class and add a method or mix one in via a module, the existing instance will gain access to that method.
If all of this fails, it looks to see if it has a method_missing method, or if its class does, its parent class, etc.
My question is this: aside from examining the code by hand, or using example methods like puts "I'm on module A!", can you tell where a given method came from? Can you, for example, list an object's methods and see "this one is on the parent class, this one is on module A, this one is on the class and overrides the parent class," etc?
Object#method returns a Method object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Get the appropriate Method (or UnboundMethod) object and ask for its owner. So you could do method(:puts).owner and get Kernel.
To find which instance methods are defined on A (but not on superclasses):
A.instance_methods(false)
To find which instance methods are defined on A AND its superclasses:
A.instance_methods
To find which class (or module) a given method is defined on:
method(:my_method).owner
To find which object is the receiver for a given method:
method(:my_method).receiver
You can use Object#method. For example,
[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons>
tells that the each_cons method of an Array comes from the Enumerable module.
I am wondering if there is a Ruby method call that shows only the methods defined by the Ruby object it's called from, as opposed to all the methods defined by its ancestor classes, which is what methods seems to do.
methods takes an optional boolean parameter, which specifies whether to also list the methods from the object's class and its superclasses or just the object's singleton methods. So you can do obj.methods(false) to only get the singleton methods defined on obj.
If you want the methods defined by the object's class, but not those defined by its superclasses, you can get that by calling instance_methods(false) on the object's class, so it's obj.class.instance_methods(false).
I'm partial to obj.methods.sort but some of the other answers are better in certain cases as they describe
You can also use obj.methods.sort.grep /foo/ to find method names matching the regexp.
This is helpful when you have an idea of what you're looking for.
You have a few options - object.methods, object.public_methods, object.singleton_methods... it depends on what you want. Since they both return an array, you might want to try something like:
# obj is the current object
parent = obj.class.superclass
methods = (obj.methods - parent.methods)
I have been a Java programmer for a while and I am trying to switch to ruby for a while. I was just trying to develop a small test program in ruby and my intention is something like following.
I want to create a simple linked list type of an object in ruby; where an instance variable in class points to another instance of same type.
I want to populate and link all nodes; before the constructor is called and only once. Something that we'd usually do in Java Static block.
Initialize method is a constructor signature in ruby. Are there any rules around them? Like in Java you cannot call another constructor from a constructor if its not the first line (or after calling the class code?)
Thanks for the help.
-Priyank
I want to create a simple linked list type of an object in ruby; where an instance variable in class points to another instance of same type.
Just a quick note: the word type is a very dangerous word in Ruby, especially if you come from Java. Due to an historic accident, the word is used both in dynamic typing and in static typing to mean two only superficially related, but very different things.
In dynamic typing, a type is a label that gets attached to a value (not a reference).
Also, in Ruby the concept of type is much broader than in Java. In Java programmer's minds, "type" means the same thing as "class" (although that's not true, since Interfaces and primitives are also types). In Ruby, "type" means "what can I do with it".
Example: in Java, when I say something is of type String, I mean it is a direct instance of the String class. In Ruby, when I say something is of type String, I mean it is either
a direct instance of the String class or
an instance of a subclass of the String class or
an object which responds to the #to_str method or
an object which behaves indistinguishably from a String.
I want to populate and link all nodes; before the constructor is called and only once. Something that we'd usually do in Java Static block.
In Ruby, everything is executable. In particular, there is no such thing as a "class declaration": a class body is just exectuable code, just like any other. If you have a list of method definitions in your class body, those are not declarations that are read by the compiler and then turned into a class object. Those are expressions that get executed by the evaluator one by one.
So, you can put any code you like into a class body, and that code will be evaluated when the class is created. Within the context of a class body, self is bound to the class (remember, classes are just objects like any other).
Initialize method is a constructor signature in ruby. Are there any rules around them? Like in Java you cannot call another constructor from a constructor if its not the first line (or after calling the class code?)
Ruby doesn't have constructors. Constructors are just factory methods (with stupid restrictions); there is no reason to have them in a well-designed language, if you can just use a (more powerful) factory method instead.
Object construction in Ruby works like this: object construction is split into two phases, allocation and initialization. Allocation is done by a public class method called allocate, which is defined as an instance method of class Class and is generally never overriden. It just allocates the memory space for the object and sets up a few pointers, however, the object is not really usable at this point.
That's where the initializer comes in: it is an instance method called initialize, which sets up the object's internal state and brings it into a consistent, fully defined state which can be used by other objects.
So, in order to fully create a new object, what you need to do is this:
x = X.allocate
x.initialize
[Note: Objective-C programmers may recognize this.]
However, because it is too easy to forget to call initialize and as a general rule an object should be fully valid after construction, there is a convenience factory method called Class#new, which does all that work for you and looks something like this:
class Class
def new(*args, &block)
obj = alloc
obj.initialize(*args, &block)
return obj
end
end
[Note: actually, initialize is private, so reflection has to be used to circumvent the access restrictions like this: obj.send(:initialize, *args, &block)]
That, by the way, is the reason why to construct an object you call a public class method Foo.new but you implement a private instance method Foo#initialize, which seems to trip up a lot of newcomers.
To answer your question: since an initializer method is just a method like any other, there are absolutely no restrictions as to what you can do whithin an initializer, in particular you can call super whenever, wherever, however and how often you want.
BTW: since initialize and new are just normal methods, there is no reason why they need to be called initialize and new. That's only a convention, although a pretty strong one, since it is embodied in the core library. In your case, you want to write a collection class, and it is quite customary for a collection class to offer an alternative factory method called [], so that I can call List[1, 2, 3] instead of List.new(1, 2, 3).
Just as a side note: one obvious advantage of using normal methods for object construction is that you can construct instances of anonymous classes. This is not possible in Java, for absolutely no sensible reason whatsoever. The only reason why it doesn't work is that the constructor has the same name as the class, and anonymous classes don't have a name, ergo there cannot be a constructor.
Although I am not quite sure why you would need to run anything before object creation. Unless I am missing something, shouldn't a list basically be
class List
def initialize(head=nil, *tail)
#head = head
#tail = List.new(*tail) unless tail.empty?
end
end
for a Lisp-style cons-list or
class List
def initialize(*elems)
elems.map! {|el| Element.new(el)}
elems.zip(elems.drop(1)) {|prv, nxt| prv.instance_variable_set(:#next, nxt)}
#head = elems.first
end
class Element
def initialize(this)
#this = this
end
end
end
for a simple linked list?
You can simply initialize your class variables in the class body, outside of any method declaration. It will behave like a static initializer in Java:
class Klass
##foo = "bar"
def sayFoo
puts ##foo
end
def self.sayFoo
puts ##foo
end
end
The class field ##foo is here initialized to "bar".
In ruby object creation works like this
class Class
def new(*args)
obj= self.allocate # get some memory
obj.send(:initialize) # call the private method initialize
end
end
Object#initialize is just an ordinary private method.
If you wan't something to happen before Object#initialize you have to write your own Class#new. But I see no reason why you would want to do that.
This is basically the same answer paradigmatic gave back in '09.
Here I want to illustrate that the "static initializer" can call other code. I'm simulating a scenario of loading a special user once, upon class initialization.
class Foo
def user
"Thomas"
end
end
class Bar
##my_user = Foo.new.user
def my_statically_defined_user
##my_user
end
end
b = Bar.new
puts b.my_statically_defined_user # ==> Thomas