On Aug 14, 2011, at 11:40 AM, Iki Baz Castillo wrote:

> 2011/8/14 Chris White <cwprogram / live.com>:
>> This behavior can fortunately be overridden by simply overriding the hello method in the B class, meaning that it will use the constant defined in B instead
> 
> Yes, but it requires duplicating code. In my case I've a server class:
> 
> 
> class Server
>  def self.foo
>    puts "I listen in IP #{IP}"
>  end
> end
> 
> 
> and then some classes inhereting from it:
> 
> 
> class UdpServer < Server
>  IP = "1.2.3.4"
> end
> 
> class TcpServer < Server
>  IP = "1.2.3.5"
> end
> 
> 
> Of course "TcpServer.foo" fails:
> 
>  NameError: uninitialized constant Server::IP
> 

I suppose the question then becomes why they have to be constants at that level. By using a module and doing a mixin (as I notice that Philip just mentioned as I'm writing this):

-------------------------------------
module Server
  def listen(ip)
    # Would most likely set instance variable @ip for later use
    @ip = ip
    puts "Listening on #@ip"
  end
end

class UdpServer
 include Server

 def listen(ip)
  puts "UDP Listen"
  super
 end
end

class TcpServer
 include Server
end

TcpServer.new.listen("1.2.3.4")
UdpServer.new.listen("1.2.3.5")
-------------------------------------

The listen logic is centralized, and as shown in the UdpServer class, you can override the Server listen and still call its core functionality through `super`. This works out because including modules inserts into the object hierarchy as shown by doing a p TcpServer.ancestors:

[TcpServer, Server, Object, Kernel, BasicObject] 

Regards,
Chris White