Reputation: 7572
I'm writing a Ruby class that extends TCPSocket
. Assume it looks something like this:
class FooSocket < TCPSocket
def hello
puts 'hello'
end
end
I have a TCPServer
listening for incoming connections
server = TCPServer.new 1234
socket = server.accept
When my server finally accepts a connection, it will return a TCPSocket
. However, I want a FooSocket
so that I can call socket.hello
.
How can I change TCPSocket
into a FooSocket
?
I could duck-punch the methods and attributes I want directly onto the TCPSocket
class, but I'm using it elsewhere and so I don't want to do that.
Probably the easiest solution is to write a class that encapsulates a TCPSocket
, and just pass the socket returned by accept
as a param. However, I'm interested to know how to do it through inheritance—I've been trying to bend my mind around it but can't figure it out.
Thanks in advance.
Upvotes: 1
Views: 332
Reputation: 15171
I think that the easiest way to do that would be to make FooSocket
a module, and then extend
it into your TCPSocket
s that need the special methods. Here are some examples of how this could be used:
module FooSocket
def hello
self.puts 'hello' # could also be written without the 'self',
end # but it is clearer this way because it may
end # be mistaken for the Kernel method.
server = TCPServer.new 1234
socket = server.accept.extend FooSocket
You could also easily override TCPServer
to return one of these:
class TCPServer
alias old_accept accept
def accept
old_accept.extend FooSocket
end
end
If you didn't want to override standard classes, you could define a singleton class on your server (which is what I would do) because you will most likely only have one server. To do this, replace the line class TCPServer
in the above example with class << server
.
Upvotes: 1
Reputation: 19485
You would need to override accept
in the TCPServer
class to return a FooSocket
instead of a TCPSocket
, either via reopening the class, or subclassing and using that. Your idea of dressing up an instance of TCPSocket
after it's been returned by accept
is cleaner I think.
Upvotes: 0