Well House Consultants Ltd.
spacer spacer
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
Solution Centre
At Well House Consultants, we provide training courses on subjects such as Perl, Python, Tcl/Tk, PHP and MySQL. We're asked (and answer) many questions, and answers to those which are of general interest are published in this area of our site.

>> link to our solutions centre home page

>> link to Ruby - More Classes and Objects
>> link to Ruby Miscellany
>> link to resource index - Ruby
MODULES IN RUBY
As your program and range of names grows, you may find that you have code that's going to cause potential name space conflicts - repeated names. That was someting that OO elegantly solves for classes of objects, but perhaps you want the equivalent of a class that doesn't instantiate anything? You're looking for a NAMESPACE that's loaded in - probably with a REQUIRE from a MODULE. Example to follow .... but we can't stress the importance of namespaces and modules as your application grows. Not put too strongly, all the standard stuff in the libraries is in modules, and it's a very good ides for you to mimic the principle. Here's an example module: module Taxcalc VAT_RATE = 17.5 def Taxcalc.net(gross) net = gross / (100.0 + VAT_RATE) * 100.0 return net end def Taxcalc.tax(gross) tax = gross - net(gross) end end and a program to use it: require "taxcalc" amount = 70.50 shopkeeper = Taxcalc.net(amount) vatman = Taxcalc.tax(amount) print "#{vatman} to the taxman\n" print "#{shopkeeper} to the supplier\n" print "Tax rate is #{Taxcalc::VAT_RATE}\n" Note that we preced methods with "modulename." so that they're just like a static method, and we preced variables within the module with :: - not something you'll do all the time, but useful (in our example) to get directly at the VAT rate. The programs runs as you would hope: earth-wind-and-fire:~/ruby/r119 grahamellis$ ruby wot.rb 10.5 to the taxman 60.0 to the supplier Tax rate is 17.5 earth-wind-and-fire:~/ruby/r119 grahamellis$
MIXINS
If you include a module within a class, then the members of that module also become available as methods in the class. This is a superb way to add in functionality to a whole lot of classes, and in essence does away with any need for multiple inheritance in very much the same way that Java's interfaces to away with the need for multiple inheritance in that language. Let's define an application with a a class of invoice objects, and then mix in an updated tax module that defines instance methods as well as module/class methods. Here's the updates tax module - remember, this is going o be mixed in so it contains a number of methods I want to pull into my Invoice class but no actual objects. module Tcalc VAT_RATE = 17.5 def getnet net = @howmuch / (100.0 + VAT_RATE) * 100.0 return net end def gettax tax = @howmuch - self.getnet end end And here's the code that calls in those methods into the Invoice class require "tcalc" class Invoice include Tcalc # The line that mixes def initialize(what,howmuch) @what = what @howmuch = howmuch end def getgross return @howmuch end def getwhat return @what end end bills = [Invoice.new("Stefano",240.00), Invoice.new("Andy",180.00), Invoice.new("Lionel",80), Invoice.new("Bruce",60)] account_line = "%-20s %8.2f %8.2f %8.2f\n" acl2 = account_line.gsub(".2f","s") ntot = ttot = gtot = 0.0 print acl2 % ["Descripton", "net", "tax", "gross"] print acl2 % ["", "=====", "=====", "====="] bills.each do |bill| person = bill.getwhat ntot += (net = bill.getnet) ttot += (tax = bill.gettax) gtot += (gross = bill.getgross) print account_line % [person, net, tax, gross] end print acl2 % ["", "=====", "=====", "====="] print account_line % ["TOTAL", ntot, ttot, gtot] And the result of running that code earth-wind-and-fire:~/ruby/r119 grahamellis$ ruby mixdem.rb Descripton net tax gross ===== ===== ===== Stefano 204.26 35.74 240.00 Andy 153.19 26.81 180.00 Lionel 68.09 11.91 80.00 Bruce 51.06 8.94 60.00 ===== ===== ===== TOTAL 476.60 83.40 560.00 earth-wind-and-fire:~/ruby/r119 grahamellis$
USING THE COMPARABLE MIXIN
One of the big uses of mixins in Ruby is to bring in standard groups of methods to your own class. A really good example of this is the Comparable module .... if you want to redefine the six operators < <= > >= == and <=> in a class that you've written, then you can do so, or you can make your life easy by using Comparable and just redefining <=>. Let's compare the delivery order of some letters for Postman Pat, who has gone high Tech and has Ruby doing his sorting for him ... with the assitance of Jess the cat. "This demonstration defines a class of objects of type Delivery which are house numbers and the name of the recipient. The postman needs to see which object to deliver first and which second, and in order to do so he goes up the even numbers then back down the odd numbers. For readers who are not from the UK, British streets are usually numbered back and forth across the road so that you have 1,3,5,7 etc on one side and 2,4,6,8 etc on the other. And with modern busy traffic, the postman does NOT want to keep crossing!!" class Delivery include Comparable def initialize(number,name) @name=name @number=number end def getnumber @number end def <=> (partner) print "I'll ask Jess\n" return -1 if @number.modulo(2) != 0 and partner.getnumber.modulo(2) == 0 return 1 if @number.modulo(2) == 0 and partner.getnumber.modulo(2) != 0 return partner.getnumber <=> @number if @number.modulo(2) == 0 return @number <=> partner.getnumber end def to_s "Deliver to #{@name} at #{@number}" end end gordon = Delivery.new(10,"Mr Dodge") graham = Delivery.new(404,"Mr Ellis") reggie = Delivery.new(22,"Dr Dodson") kim = Delivery.new(25,"Ms Ellis") chris = Delivery.new(15,"Mr Ellis") print kim," before ",chris,"\n" if kim < chris print chris," before ",kim,"\n" if kim >= chris print reggie," before ",chris,"\n" if reggie < chris print chris," before ",reggie,"\n" if reggie >= chris print reggie," before ",graham,"\n" if reggie < graham print graham," before ",reggie,"\n" if reggie >= graham print reggie," before ",gordon,"\n" if reggie < gordon print gordon," before ",reggie,"\n" if reggie >= gordon print reggie," before ",kim,"\n" if reggie < kim print kim," before ",reggie,"\n" if reggie >= kim And running the program: earth-wind-and-fire:~/ruby/r119 grahamellis$ ruby pat.rb I'll ask Jess I'll ask Jess Deliver to Mr Ellis at 15 before Deliver to Ms Ellis at 25 I'll ask Jess I'll ask Jess Deliver to Mr Ellis at 15 before Deliver to Dr Dodson at 22 I'll ask Jess I'll ask Jess Deliver to Mr Ellis at 404 before Deliver to Dr Dodson at 22 I'll ask Jess Deliver to Dr Dodson at 22 before Deliver to Mr Dodge at 10 I'll ask Jess I'll ask Jess I'll ask Jess Deliver to Ms Ellis at 25 before Deliver to Dr Dodson at 22 earth-wind-and-fire:~/ruby/r119 grahamellis$
See also

Well House Consultants provides training courses ... that's our main business ... and from time to time we write additional technical notes and articles to widen the issues covered for a particular group of trainees. Longer articles of more general interest are published here in our solutions centre. You'll also find shorter items at The Horse's Mouth and delegate's questions answered at the Opentalk forum.
spacer

You can Add a comment or ranking to this page

WELL HOUSE CONSULTANTS LTD • 404, The Spa • Melksham, Wiltshire SN12 6QL • United Kingdom
PHONE: 01144 1225 708225 • FACSIMILE 01144 1225 793803 • EMAIL: info@wellho.net
You are currently on our United States site. Change your country.
Privacy and Copyright StatementTerms and Conditions
Updated Friday, April 26th 2024 • © Well House Consultants, 2024

This is page http://www.wellho.net/solutions/ruby-modules-mixins-and-comparators.html