1

Here is my situation:

  • XMLRPC::Client has a proxy constructor, new3, that takes a hash of options. It takes out the individual values to then delegate the construction to the default initializer, initialize
  • I am deriving from XMLRPC::Client. I want a class that is XMLRPC::Client but with some added functionality.
  • I want to be able to instantiate this derived class using a hash of options as well. This means that in my derived class' initializer, I have to somehow instantiate super using the new3 proxy constructor.

My Question Is if this is possible. If not, then is the only way to solve this is to practically 'copy and paste' the code within the XMLRPC::Client.new3 method into my derived class' constructor?

The reason I'm asking this is simply to see if there is a way of solving this problem, since there is this recurring theme of DRY (Don't Repeat Yourself) within the Ruby community. But of course, if this is the only way, it wont kill me.

Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123
  • Wow, uh, can you clean up the question so it reflects the question you want to ask? You're asking a couple questions now: "my question is", "I will restate my question", "My Question is". It's ok to gut it if that's what it takes, just keep it on the same topic and generally on the same question. – the Tin Man Nov 23 '10 at 00:48
  • @Greg: I did clean up the question, it's just that I did a 'strikethrough' on the previous body of the question instead of flat out removing it in case people were reading it. I'm removing it now :) I really do hope you didn't attempt to read through the striked-out portion of the question, haha, it was striked out for a reason. – Jorge Israel Peña Nov 23 '10 at 01:02

3 Answers3

1

You should probably be able to call new3 on you subclass

class MyClient < XMLRPC::Client
end
MyClient.new3({})

Or overwrite it if you need to do extra stuff:

class MyClient < XMLRPC::Client
  def self.new3(args)
    client = super(args)
    # do some more stuff
    client
  end
end
MyClient.new3({})
Petrik de Heus
  • 970
  • 6
  • 9
1

Make a new class method in your derived class (much like they did to make new3 in the first place):

class MyDerived < XMLRPC::Client
    def self.new3(hashoptions)
         client = XMLRPC::Client.new3(hashoptions)
         # Do further initialisation here.
    end
end

myone = MyDerived.new3(:abc => 123, ...)

super only works in initialize (and only changes the parameters to the superclass's initialize), so it doesn't apply here.

Asherah
  • 18,948
  • 5
  • 53
  • 72
  • Judging from these answers, I think my question is too misleading, I will re-state it. I don't mean that I want a new3 method in my derived class. Also, I'm deriving from XMLRPC::Client, so it doesn't make much sense to make it client =, or am I mistaken? – Jorge Israel Peña Nov 22 '10 at 23:35
  • 1
    You basically need to create a factory method that returns an instance of the object you want, constructed the way you want. You cannot overload constructors in ruby the way you would in java, so you have to do this. – Jeremy Nov 22 '10 at 23:43
  • 1
    @Jorge: You do if it's a class method (note that it's `self.new3`). In this case, are you just wanting `MyDerived.new` to use `XMLRPC::Client.new3`? Just overload `self.new`, in that case. – Asherah Nov 23 '10 at 23:10
1

I am only posting an answer supplement the other answers by showing you how XMLRPC's code is written

def new3(hash={})

      # convert all keys into lowercase strings
      h = {}
      hash.each { |k,v| h[k.to_s.downcase] = v }

      self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'],
               h['use_ssl'], h['timeout'])
    end

http://www.ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/xmlrpc/rdoc/classes/XMLRPC/Client.html

Jeremy
  • 22,188
  • 4
  • 68
  • 81
  • Yes Jeremy, I mentioned this in my question ... I know how new3 is defined. My question is if I **must** copy and paste the code within new3 to my derived class' constructor. It just doesn't make much sense to repeat the code, especially since it's within the class I'm deriving from. My question _is_ if this is the **only way**, if so, that's fine, I'll do it. – Jorge Israel Peña Nov 22 '10 at 23:49
  • Where did I or anybody else say you _must_ copy and paste code? All you need to do is call `new3` inside your class method and return that instance. Just like the how `new3` calls `new`. – Jeremy Nov 22 '10 at 23:50
  • I'm not accusing anyone of said that ... I'm _asking_ if that's the case. The problem is that I _did_ call new3 but it keeps saying it is an undefined method. – Jorge Israel Peña Nov 22 '10 at 23:53
  • Alright, thanks, so I take it there isn't really a way of doing what I wanted. No problem, I'll just re-use the code from within new3 in my derived class' initializer. – Jorge Israel Peña Nov 23 '10 at 00:03
  • OK, so that brings me to ask: What's wrong with Arlen's answer? Do you still need access to the super class's `new3`? – Jeremy Nov 23 '10 at 00:14
  • To be honest, I'm confused. I don't understand how Arlen's answer is related to my question. he is saying 'client = XMLRPC::Client.new3', but client _is_ the class that I'm writing, do you understand my confusion? I don't know why my class should have a client given that it _is_ the client. I'm not saying it's wrong, I'm just confused. – Jorge Israel Peña Nov 23 '10 at 00:37
  • It is awkward. What Arlen was saying is to create an instance in a class method and return it. It's a class method, which doesn't operate on a specific instance. But, after looking at this a bit more, this really is a limitation imposed by how `Client` is implemented with factory methods. You really would be better off copying the code in this case. The code is pretty straight forward, and really only serves to clean up the hash before calling the real constructor. – Jeremy Nov 23 '10 at 00:49
  • Yeah, I realize the code is pretty straightforward anyways, not a big deal, my purpose in posting this question was just to make sure that I wasn't going about it 'the wrong way', since Rubyists seem to preach DRY methods everywhere. I just went ahead and copied the code and everything works fine :) I just figured perhaps there was a 'trick' or something to go around this, but it's no big deal. – Jorge Israel Peña Nov 23 '10 at 01:01
  • Yeah, it's unfortunate. Good luck. – Jeremy Nov 23 '10 at 01:30
  • `super` does work on subclasses. Calling new3 on a subclass will return an instance of that subclass: `Class.new(XMLRPC::Client).new3({})`. Overwriting `self.new3` in your subclass will allow you to use `super({})` to create an instance of the subclass. – Petrik de Heus Nov 23 '10 at 21:04