Is is possible to do something like super.super in the overriden method? That is, to bypass the direct parent's super and call "grandparent's" super?
This is not recommended, but what you want is possible like this:
grandparent = self.class.superclass.superclass
meth = grandparent.instance_method(:the_method)
meth.bind(self).call
This works by first getting the grandparent class, then calling instance_method on it to get an UnboundMethod representing the grandparent's version of the_method. It then uses UnboundMethod#bind and Method#call to call the grandparent's method on the current object.
you could modify the method's arguments to allow some kind of optional 'pass to parent' parameter. in the super class of your child, check for this parameter and if so, call super from that method and return, otherwise allow execution to continue.
class Grandparent; def method_name(opts={}); puts "Grandparent called."; end; end
class Parent < Grandparent
def method_name(opts={})
return super if opts[:grandparent]
# do stuff otherwise...
puts "Parent called."
end
end
class Child < Parent
def method_name(opts={})
super(:grandparent=>true)
end
end
ruby-1.9.2-p0 > Child.new.method_name
Grandparent called.
=> nil
otherwise i agree with #Femaref, just b/c something is possible doesn't mean it's a good idea. reconsider your design if you think this is necessary.
Considering this is breaking one of the principles of OOP (encapsulation), I dearly hope it isn't possible. Even the case of you trying to do this speaks of a problem with your design.
Related
I found the below working solutions (link 1, link 2) which call the grandparent method but without any parameters. Does anyone know how to call the grandparent method with parameters?
class GrandParent
def fun(word)
puts word
end
end
class Parent < GrandParent
def fun(word)
puts word + 'end'
end
end
class Child < Parent
def fun(word)
GrandParent.instance_method(:fun).bind(self).call
end
end
You can pass parameters directly to call like this:
class Child < Parent
def fun(word)
GrandParent.instance_method(:fun).bind(self).call(param1, param2)
end
end
call accepts parameters
GrandParent.instance_method(:fun).bind(self).call word
I don't know your use case, but this is a Really Bad Idea™. It creates unnecessary dependencies directly between Child and GrandParent such that all kinds of normally reasonable refactoring would result in a crash e.g. moving fun to only be implemented in Parent, changing Parent to subclass a different but similar parent, etc.
This is something I've wondered about for years: is it more efficient to check if an object has a method and then, if it does, call the method, OR always have a method that does nothing, always call that method, and subclasses should override that method as needed.
Consider this example:
class Base
def mymethod
respond_to?(:hook) and hook()
puts 'stuff in mymethod'
end
end
class SubClass < Base
def hook
puts 'stuff in hook'
end
end
So in this situation we've basically added an event handler. If a subclass has a method called hook then that method is called in mymethod. This is a pretty common design technique. But, of course, that requires checking if the method exists.
Another technique to implement the same result would be to design Base like this:
class Base
def mymethod
hook()
puts 'stuff in mymethod'
end
def hook
end
end
Now you don't have to check every time if there's a method called hook, but you do have to call that method every time, even if it does nothing.
So which is more efficient? Which is easier for the programmer to understand? Is the difference so small that it's merely a matter of personal preference?
Short answer: It's so trivial that you shouldn't care.
Long answer:
require 'benchmark'
class Base
def mymethod
respond_to?(:hook) and hook()
end
end
class SubClass < Base
def hook
end
end
class Parent
def mymethod
hook
end
def hook
end
end
class Child < Parent
end
s = SubClass.new
c = Child.new
n = 10000000
Benchmark.bm(7) do |x|
x.report(:respond_to?) { n.times {s.mymethod} }
x.report(:empty) { n.times {c.mymethod} }
end
Result:
user system total real
respond_to? 1.263308 0.011612 1.274920 ( 1.327659)
empty 0.789442 0.010208 0.799650 ( 0.900536)
So using respond_to? is slightly slower than using empty method.
Offtopic a bit, but I'd say using respond_to? with an implicit receiver in the way you propose is a code smell - it means that you are doing some weird things that break subtyping (LSP).
Sometimes it might be really necessary for some black metaprogramming magic, debugging, hotfixing the live app etc - but I bet in such cases you won't ask questions like this (you will know for sure why do you do this, end efficiency will be less of a problem for sure).
So, as for me, the question is not about efficiency. Always "respect" (follow) LSP if you can and play with respond_to? only if you must (and in this case performance might be not the main criteria)
respond_to? will always be slower. It will incur at least one (in the negative case), and possibly two (in the positive case) method calls. The empty base method case, on the other hand, is just the one method call.
Method calls are fast, but if you're really trying to micro-optimize, all else held constant, reducing the number of method calls will result in faster code.
Say I have a parent class:
class Stat
def val
raise "method must be implemented by subclass"
end
end
And a subclass:
class MyStat < Stat
def val
#performs costly calculation and returns value
end
end
By virtue of extending the parent class, I would like the subclass to not have to worry about caching the return value of the "val" method.
There are many patterns one could employ here to this effect, and I've tried several on for size, but none of them feel right to me and I know this is a solved problem so it feels silly to waste the time and effort. How is this most commonly dealt with?
Also, it's occurred to me that I may be asking the wrong questions. Maybe I should't be using inheritance at all but composition instead.
Any and all thoughts appreciated.
Edit:
Solution I went with can be summed up as follows:
class Stat
def value
#value ||= build_value
end
def build_value
#to be implemented by subclass
end
end
Typically I use a simple pattern regardless of the presence of inheritance:
class Parent
def val
#val ||= calculate_val
end
def calculate_value
fail "Implementation missing"
end
end
class Child < Parent
def calculate_val
# some expensive computation
end
end
I always prefer to wrap the complex and expensive logic in its own method or methods that have no idea that their return value will be memoized. It gives you a cleaner separation of concerns; one method is for caching, one method is for computing.
It also happens to give you a nice way of overriding the logic, without overriding the caching logic.
In the simple example above, the memoized method val is pretty redundant. But the pattern it also lets you memoize methods that accept arguments, or when the actual caching is less trivial, maintaining that separation of responsibilities between caching and computing:
def is_prime(n)
#is_prime ||= {}
#is_prime[n] ||= compute_is_prime
end
If you want to keep the method names same and not create new methods to put logic in, then prepend modules instead of using parent/child inheritance.
module MA
def val
puts("module's method")
#_val ||= super
end
end
class CA
def val
puts("class's method")
1
end
prepend MA
end
ca = CA.new
ca.val # will print "module's method" and "class's method". will return 1.
ca.val # will print "module's method". will return 1.
I am working on a project that requires very specific methods to be called on an ActiveRecord::Relation object. These methods cannot extend ActiveRecord::Relation because the Class has it's own initialize method to determine if the object should be collected. I have tried a dozen ways to handle this but because of method chaining in AR I have been unable to accomplish this. Currently I have monkey patched ActiveRecord::Relation with a method that converts it like so:
module ActiveRecord
class Relation
def to_claim_set
exec_queries unless loaded?
ClaimSet.new(#records)
end
end
end
Firstly I am sure this is an improper way to handle it. Secondly this causes me to have to call #to_claim_set constantly throughout the application.
I am hoping someone can assist on making this the default return after all method chaining is complete.
What I am hoping for is something like
Claim.policy_number('913006')
#=> ClaimSetObjectHere
But I need it to support chaining like AR does so that things like
Claim.policy_number('913006').by_program('Base')
#=> ClaimSetObjectHere
I also tried to patch the #where method inside Claim which works great unless I use a scope or I chain methods in which case it complains that ClaimSet does not define default_scoped?.
Any insight would be greatly appreciated. As for "Why would you want to do this" like I said I am constantly calling this method throughout the application and I need the methods defined in ClaimSet for this to function properly.
Note: This is being used outside of rails
Okay so what I ended up doing was imposing a wrapper for ActiveRecord::Relation like so:(removed specific business logic for brevity)
class ClaimSet
def initialize(object)
process_target(object)
# ...
end
# ...
def respond_to_missing?(method_name,include_private=false)
#target.respond_to?(method_name)
end
def method_missing(method_name, *args, &block)
if #target.respond_to?(method_name)
ClaimSet.new(#target.send(method_name,*args,&block))
else
super
end
end
private
def process_target(object)
#target = object if object.is_a?(ActiveRecord::Relation)
#target = object.target if object.is_a?(ClaimSet)
end
end
Then in the Claim class.
class Claim < ActiveRecord::Base
class << self
def where(*args)
ClaimSet.new(super(*args))
end
def localized_scope(name,proc)
scope_proc = lambda do |*args|
ClaimSet.new(proc.call(*args))
end
singleton_class.send(:define_method,name,scope_proc)
end
end
end
Then I define all my scopes as localized_scope e.g.
localized_scope :policy_number, ->(policy_number){where(policy_number: policy_number)}
Now it always returns a ClaimSet in place of an ActiveRecord::Relation for #where and #localized_scope and supports method chaining through #method_missing. It also removes the monkey patch on ActiveRecord::Relation.
If you have any other suggestions please let me know as I would be glad to entertain other ideas but this works for the time being.
Can someone explain the difference between initializing "self" and having #variables when defining classes?
Here's an example
class Child < Parent
def initialize(self, stuff):
self.stuff = stuff
super()
end
end
So in this case, wouldn't I be able to replace self.stuff with #stuff? What's the difference? Also, the super() just means whatever is in the Parent initialize method the Child should just inherit it right?
In general, no, self.stuff = stuff and #stuff = stuff are different. The former makes a method call to stuff= on the object, whereas the latter directly sets an instance variable. The former invokes a method which may be public (unless specifically declared private in the class), whereas the latter is always setting a private instance variable.
Usually, they look the same because it is common to define attr_accessor :stuff on classes. attr_accessor is roughly equivalent to the following:
def stuff
#stuff
end
def stuff=(s)
#stuff = s
end
So in that case, they are functionally identical. However, it is possible to define the public interface to allow for different results and side-effects, which would make those two "assignments" clearly different:
def stuff
#stuff_called += 1 # Keeps track of how often this is called, a side effect
return #stuff
end
def stuff=(s)
if s.nil? # Validation, or other side effect. This is not triggered when setting the instance variable directly
raise "Argument should not be nil"
end
#stuff = s
end
You actually can't use self.stuff= unless you specifically create an attr_writer for modifying that value.
In fact, these are equivalent:
class Child
attr_writer :stuff
end
class Child
def stuff=(val)
#stuff = val
end
end
It is more common to use an attr_writer if that is the functionality you want, rather than the explicit method. But you will often use an explicit method if you want to perform extra error checking or change the way the assignment works.
To your question of when to use #stuff = and when to use self.stuff =, I would use the former if you only have simple assignments and if your class is simple, and would move towards the latter if your requirements might become more complicated. There are many other reasons too, but it's more a matter of style than anything else.