Smalltalk Programming Tutorial. Classes. Class Hierarchy. Sending messages to ByteString class (i.e. Strings).

Tutorial 3. Strings



More Tutorials
C Programming Tutorial
T223

HTML Tutorial & Web Design
T170,T171 and TT180

Search this site

Home

 

Tutorials
| 1. Starting Smalltalk, and Terminology | 2. Precedence Rules | 3. Classes - Strings | 4. Class Browser | 5. Variables | 6. Error Messages | 12. Control Structures | 16. Dialogs | 23. Collection class | 39. OpenGUI |

 

Information
| Smalltalk Books | Student Software & Books | Hints & Tips | Sites | Download Smalltalk | Coloured code | Download Documents | ASCII Codes |

 

Smalltalk Index

 

 

 

 

Contents

Exercise Solutions

Instructions

In order to follow this tutorial Click on the following link, which will open a separate window, print out the single page, then close the page. Collection Class Hierarchy
.
This page has a diagram of of the Collection Class Hierarchy that you should have available to help in understanding this tutorial.

 


The OU ( Open University ) M206 Computing an Object-oriented approach course, talks of attributes in the early part of the course. Later the correct term instance variables is used. I think that students who have programmed in other languages will grasp Smalltalk terminology better thinking of instance variables rather than attributes. Methods are also very similar to functions used in other languages.

Classes

  • As with real-world classification, a class groups together objects that the programmer considers to be similar.
  • Classes are arranged in a hierarchy that describes the behaviour of a set of objects of the same kind.
  • The class hierarchy gives the description of a set of objects with similar characteristics and attributes (instance variables). See the comment for the class in the class browser.
  • For example the Open University has created class Person, a subclass of Object.
    • The attributes (instance variables) of the class are Person name and address.
    • If a programmer required additional instance variables, such as telephoneNumber and/or dateOfBirth, the programmer could add these.
      • Note how spaces are not allowed in instance variables names. The capitalisation of the first letter, of what would be a separate word etc. is the norm. Examples noOfTickets, creditCardNo, postCode
  • During the course you will create new classes.
  • The M206 LearningWorks, and other programs have been set up with an existing "Library" of Classes installed.
  • Classes usually have ---
    • Comments
    • Names, such as Object, Collection, Person, Date, Number, etc. Class names start with a capital letter.
    • Instances. Note that Abstract Classes do not have instances. See Abstract classes below.
      • An object that belongs to a given class is described as an instance of that class.
      • Instances of a class are created myFrog :=Frog new Would create an instance of the class Frog, the name of the instance myFrog is a temporary variable.
      • Instance names start with a lower case letter.
    • Instance variables, these are initially called attributes by the OU Course Team.
      • Do not confuse Instances with instance variables.
      • Instance variables refer to specific information about an instance.
        • Example The instance of the class Frog, myFrog has instance variables position and colour. The value of these instance variables may be 1 and Green respectably. These values can be changed using the 2 setter methods position: and colour: .
    • Class variables.
    • Methods
  • Some classes are Abstract classes.
    • These are classes that that
      • Do not have instances.
      • Specify common behaviour for there subclasses.
      • Abstract classes have special methods in them.
        1. Base methods.
        2. Abstract methods.
        3. Template methods.
        Which are different ways of how messages are set up for subclasses.
    • They are discovered at the design stage, when it can be seen that several classes share common characteristics.
      • The OU course introduces the abstract class Amphibian, for the classes Frog, Toad and HoverFrog, in Chapter 21 Page 8.
      • This abstract class appears in LB 22 for the first time.

 

Top of Page

Class Inheritance Hierarchy

A diagram of the class hierarchy looks like a tree root structure, and it represents the subclass and superclass relationship between classes of the hierarchy . The diagram below, on the left represents a very small section of this hierarchy.

 

Section of {hierarchy image} The colours are used to explain the layout.
Red Is the Object class. There is only 1 class at this level, the top of the root system, i.e. the base of the tree trunk.
Green These are the subclasses of Object. Object is their superclass. There are approx. 125 classes at this level. In turn each one may have there own subclasses, but not all do, see the centre one.
Yellow These classes each have a superclass, and also have one or more subclasses.
Blue The diagrammatic root tip classes each have a superclass, but don't have any subclasses. Note that the green, central box could be coloured blue.
  • The diagram only shows 4 levels.
  • You will discover in the exercises in this tutorial, there are more levels than this.
  • What is important for the classes lower down in this hierarchy is the direct route back to object.
    • This route determines theI nheritance relationship between classes and what messages that an instance of a class will understand, because the messages are inherited from classes higher in the hierarchy
    • Classes higher in the hierarchy have more general (common) characteristics.
    • Classes lower in the hierarchy have more specific characteristics and inherit the general characteristics from the classes higher in the hierarchy .
    • When a class inherits from another class it receives all that class's methods and variables, and is then able to define incrementally its own additional methods and variables.
    • Classes higher in the hierarchy can NOT use the more specific instance variables and methods that are in classes lower down the hierarchy.
    • They must be in the classes along this route. This is demonstrated in this tutorial.
    • Only 1 class at each level is on any specific route

 

every subclass should be a specific kind of its superclass. This is reflected in the inheritance hierarchy by classes higher in the hierarchy representing more general (common) characteristics, while classes lower in the hierarchy representing more specific characteristics, that is, superclasses specify general characteristics which their subclasses inherit and refine to provide specific characteristics.

Top of Page

Subclass

  • A new class may be defined in terms of an existing class.
  • The new class, the subclass, requires the programmer only to specify what makes it different from the existing class, its superclass.
  • Instances of a subclass can respond to the same messages (although not necessarily with the same response) and have the same attributes as the instances of the superclass.
  • The subclass instances may have additional attributes (instance variables).
  • The subclass may define additional messages. Hence the protocol of the subclass contains (has at least all the messages of) the protocol of the superclass. For example, in the OU ( Open University ) course " Computing an Object-oriented approach, HoverFrog is a subclass of Frog . The protocol of HoverFrog objects includes that of Frog objects (left , right , home , brown , green , jump , colour: , colour and sameColourAs: ) and also has a message to which Frog objects cannot respond (message selector hover:by: ). The HoverFrog and Frog objects respond identically to the messages they have in common that are listed above. HoverFrog objects have the attributes (instance variables) of Frog objects (colour and position ) and an additional attribute (instance variables) height.
  • A subclass is any class which, when taking part in an inheritance hierarchy with another class, is the class to inherit functionality. All classes except Object are subclasses of some other class. A class can be both a subclass and a superclass if it is in the middle of an inheritance hierarchy, e.g. yellow boxes in the diagram.

 

Superclass

If B is the subclass of A, then A is the superclass of B.
  • In the Smalltalk programming language a subclass has only one superclass.
  • Any class which, when taking part in an inheritance relationship with another class, is the class from which functionality is inherited.
  • All classes except those at the 'root tips', blue boxes in the diagram, of the inheritance 'tree' are superclasses, even though they are also subclasses (except for Object).
  • A superclasses can have 1 or many subclasses.

 

Strings

Strings were mentioned in tutorial 2.
Strings are
  • Strings are enclosed in single quotes. E.g. 'Hello World '
  • I am using the name strings as a general term. The class String is an Abstract class, see Classes above.
  • You will learn the correct term during exercise 1a
  • Think of a string as a "string" of individual characters.
  • The string is actually an array of individual characters.
  • Each individual character being an element of the array.
  • They are very much like a string in any other programming language. But remember in Smalltalk the string is enclosed in single quotes.

 


Question 1 What distinguishes a string from a comment?
Go to Answer 1

 


Most books on programming show you how to create a program that will put the words Hello World onto the screen. In Smalltalk obtaining 'Hello World' as an answer to evaluating a message expression is easy. All you have to do is evaluate 'Hello World', how, see below.

 

Exercise. 1a
  1. Start up M206 LearningWorks program and select LB-12.
    • LB-12 is a download from the OU web page. If not available use either LB-13, or LB-14.
  2. Type into the expression pane, a suitable comment, e.g. "Tutorial 3. Exercise 1a. String example."
  3. Press the Enter key, to go to the next line.
  4. Type in 'Hello World'
  5. Evaluate. You can evaluate just the 'Hello World' or you can evaluate both lines. Because the "comment" is ignored in the evaluation.
  6. 'Hello World' appears in the answer pane


This exercise shows that evaluating an object name displays a textual representation of itself in the answer pane. This may appear to break the rules because it does not appear that we have sent a message to an object. What we have done is send a message to Smalltalk itself, and the object name is the argument.
Later you will discover that the textual representation of the object can be programmed by code.
This is noticeable in instances of Frog, HoverFrog, and Toad, that the OU ( Open University ) use in their Computing an Object-oriented approach course.

 

Top of Page

String class

  • String is an abstract class that is the superclass for all string implementations such as ByteString and TwoByteString and also for Symbol class.
  • Abstract classes can not have instances created .
  • ByteString is an indirect subclass of String .
    • ByteString is known as a concrete class because it can have instances.
    • An example of a ByteString is 'Hello World'.
      • A sequence of characters between single quotes.
    • TwoByteString another concrete class, very similar to ByteString. The difference is that TwoByteString can hold more "exotic" characters that require more memory. These could be the Greek characters used in mathematics, Pi Omega etc.

 

Top of Page

Workspace Comments

In tutorials 1 and 2 you learnt how comments are used in methods.
Comments can also be used in the workspace.

 

You will probably devise a system of your own of how and when you will use comments in the workspace. These comments can help you when returning to a Lb. after a break, or to check something out.
Use Workspace comments in the following exercises.

 

Ideas for comments.
  • The exercise being undertaken.
    • "Tutorial 3. Exercise 1a. String example."
    • "LB-12 Practical 1."
  • The TMA being undertaken
    • "TMA 3. Question 2 a."
  • Information
    • "The following code- Not working as expected - produces the wrong answer of ..... Correct answer is ......."
    • "The following code produces error message ............"

 

Inspecting

Inspecting is an important part of developing an expression, it allows the programmer to make checks on what has actually happened. This is more useful when an unexpected result occurs.
Inspecting objects provides additional information about that object such as its state.

 

From now on carry out inspections of objects. In order to understanding the inspecting process better, and the information obtained from inspecting objects. Do lots of them.

 


There are 2 way of inspecting.
  1. Using the "Inspect last message answer" button
  2. Using the inspect message in your expression

Top of Page

Exercise 1b. Inspecting 'Hello World' using the Inspect button.

 


Before you evaluate 'Hello World' count and remember the number of characters in the string.

 

Now evaluate 'Hello World' Then click on the "Inspect last message answer" button.

 

I will explain the Inspector window after you try the alternative way of bringing it up

 

Exercise 1c. Inspecting 'Hello World' using the inspect message.

 


Evaluate 'Hello World' inspect

 


Top of Page

Inspector window


  • An inspector is a tool used to look at the objects in the system.
  • It displays an object and its attributes (instance variables).
  • The name of the class of which the object is a member is displayed in the title bar and in a pane in the window.
  • An inspector is created by pressing the Inspect button after selecting the name of the object whose attributes (instance variables)are to be viewed.
  • An inspector opened on frog1 shows in the title bar that the object being inspected belongs to the Frog class.
  • All instances of Frog , such as frog1 , have attributes (instance variables) for position and colour .
  • These instance variable names are displayed alongside their current values.

{inspect image}

{Frog Inspector Window}

 

Note the following Inspector Windows vary slightly depending on the class they are depicting. A description for the classes ByteString and Frog follow:
  • The title in the title bar is Inspector on either ByteString or Frog, the name of the class.
  • The windows have varying number of information panes.
  • Class pane.
    • Displays the class to which the object belongs.
    • Note: The class for 'Hello World' is ByteString. The term string is a more general term. When used in Smalltalk the user is normally referring to ByteString class.
    • The class pane is usually labelled, other panes are often not labelled.
  • Unlabelled pane containing containing 'Hello World'
    • Displays the evaluation answer as a textual representation of it.
    • The textual representation for the Frog class has been programmed into a method in the class, if this had not been done the less informative default textual representation a Frog would have resulted.
  • The bottom pane, labelled Elements.
    • Use the scroll bar, or enlarge the window to see all 11 elements.
      • The elements show the position of each character. in an array of characters. Arrays are later in the course.
    • If your count of the characters in 'Hello World' came to 10, then you probably did not count the space between Hello and World. The sixth element.
    • Look at the second column where you see for Element 1$H "16r0048"
      • $ Denotes a Character object follows.
      • 16r Stands for radix 16 i.e. a hexadecimal number follows.
      • 0048 48 is the hexadecimal value for H in the ASCII codes
  • The bottom pane, for the Frog class displays a list of all the attributes (instance variables) and their current value.

 

Exercise 1d. Inspecting the Inspector Window.

 

More information can be obtained from this window. Before you do this exercise note that classes are arranged in a hierarchical system similar to that of windows and its folders. The top level is the Object class, this is similar to the C; root folder (directory). At this stage you are only going to get a "feel" of this hierarchical system.
The system looks like the roots of a tree, with the Object class being the trunk.

 

What you should remember is that a lot of information can be obtained from the Inspector. Usually the first window contains the information required. But as you will see more information is there and can be obtained by double clicking on various sections of the window.

 


Double click on ByteString in the Class pane. (Rerun Exercise 1b if you have closed the inspector window.)

 

Do not delete the new inspector window, Inspector on that appears, because further exercises will be done with it.
Look at the following in this window.
  • The title of the window is Inspector on ByteString class.
  • That the information in this window is different from the previous one.
  • Find in the bottom panes left column: superclass, subclass, organisation.
  • Superclass.
    • The superclass is ByteEncodedString
    • A class can only have 1 superclass
    • This is the class that is higher in the class hierarchy.
    • You will inspect this soon.
  • Subclasses.
    • The nil entry indicates that the ByteString class has no subclasses.
    • Subclasses is in the plural, so a class may have nil, one or many subclasses.
  • Organisation
    • Within this line pick out at: put: size
      • These are messages that you will use later in this tutorial.

 

Top of Page

Hierarchy - Exercises.

Lets look at what has been mentioned so far.
  1. ByteString has no subclasses, therefore it must be at the very tip of a root in our hierarchy root system
  2. ByteEncodedString is the superclass of ByteString. This class is hidden in the Class Browser
  3. Object class is at the top of the hierarchy and I have likened this to the tree trunk.
There are several more classes as you move from the root tip towards the trunk. I have marked these classes down with an X in the list below. Note that each indentation is showing a new level of the 'tree' hierarchy.
In the next Exercise you are going to replace the X's with the actual class.

 

Object 
        X
                X
                        X
                                X
                                        X
                                                X
                                                       ByteEncodedString
                                                               ByteString

 

The following exercise will allow you to get an insight into the hierarchy of classes.
Because in this exercise you are navigating from the 'root tip' towards the 'tree trunk' the navigation is easy, there is only 1 superclass for any one subclass.
Travelling in the other direction, the navigation can be harder, because a superclass may have several subclasses, each of these multiple subclasses gives you an alternative route though the network of 'roots' which end in many 'root tips'. For such a journey either a map of the system is required, or you need specific directions. I have provided a map for the area we are working in. You should have printed it out if you followed the instructions at the start of this tutorial. If you have not printed the Collection Class Hierarchy, click here, print then close the window. Please note that ByteEncodedString class does not appear on this "map", because ByteEncodedString is not visible in the class browser, the source of the map.

 

Exercise 1d. Hierarchy- introduction.
  1. Printout this page or write down the hierarchy list above.
  2. In the Inspector on ByteString class that you still should have open from the previous exercise. (If required repeat the last 2 exercises.)
  3. Double click on the line superclass, to bring up the Inspector on ByteString class
  4. Read the class in the superclass line and enter it in the list replacing one of the Xs. Also check your progress on the Collection Class diagram, that you have printed out.
  5. Look at the subclass line and note that this class has 4 subclasses. 3 off these subclasses are of no interest to you in this course, and are hidden from view in the class browser. But the 4th one is ByteString.
  6. Repeat steps 2 to 5, making sure that step 2 is carried out in the latest window that pops up, carry on until you reach the top of the root system i.e. Object..
    1. During these repeats, keep looking at the subclass line. You may have to enlarge the window to see all of the entries.
    2. Look for these classes:- List, Array, CharacterArray, OrderedCollection, Bag, and Set. You will be using all these classes, and some of their subclasses, in the M206 Open University (OU) course.
  7. When you reach the Object class
    1. Maximise the window.
    2. Look at the subclass line, and note that you can't read all the entries.
    3. Double click this line.
    4. Maximise the new window, in this window note the Elements pane. Scroll down this pane and note how many subclasses the Object class has. In mine there are approx. 125. Remember most of these subclasses have many subclasses of there own, which in turn have further subclasses.
    5. You may now realise why a map of the entire system is not provided. From this list of 125 subclasses the OU M206 course concentrate on only a few, such as
    6. Element Number, Name
      1. 20 BlockClosure
      2. 23 Magnitude.
      3. 49 Boolean.
      4. 62 Dialog.
      5. 70 Collection. (See your printout).

Go to Solution to ex 1d

 

Top of Page

Sending messages to ByteString


In the table below are listed the message selector's that you are going to use.
  • The names of messages do tend to inform you, to some degree, of what they will do.
  • The comment in the method will tell you, but not in easily understood plain English.
  • Note how all the classes , except one, in the Table Class column are in the hierarchy we have examined. You will find out why this one answers with an exception notifier.
    Object 
            Collection
                    SequenceableCollection
                            ArrayedCollection
                                    CharacterArray
                                             String
                                                    ByteEncodedString
                                                           ByteString
    
  • Read the information in the table below.
    • In the Class column, Total class, the number after the class displayed is the total number of different classes that the method, that is referenced by the message selector is in.
      • E.g. The method asLowercase is in 3 classes. CharacterArray, Character and Text .
      • This information can be obtained from the Class Browser.
      • Looking at the Collection Class Hierarchy Diagram printout. Starting at ByteString, CharacterArray can be found on the hierarchy route, as you travel towards Object class, Therefore the message, asLowercase is understood by a ByteString object.
    • I have therefore selected the most suitable class for you, but as already stated, one line in the table should not be there, keep an eye out for it.
Message selector Class, Total classes Example  Method Comment
 , SequenceableCollection. 3 'ab' , 'cd' "Answer a copy of the receiver concatenate with the argument, a SequenceableCollection."
concatenate: String 1 AB concatenate: CD This method uses , to concatenate. Recommend you do as well.
at: ByteString 14 '12abAB' at: anInRangeInteger "Answer the Character stored in the field of the receiver indexed by the argument. Fail if the index argument is not an Integer or is out of bounds."
At:put: ByteString 15 '12abAB' at: anInRangeInteger put: aCharacter "Store the Character in the field of the receiver indicated by the index. Fail if the index is not an Integer or is out of bounds, or if the argument is not a Character, or if the code of aCharacter does not fit in one byte."
asInteger Character $A asInteger "Answer the value of the receiver."
asIntegerArray ByteString 2 '12abAB' asIntegerArray "Answer an instance of a kind of IntegerArray whose elements are the elements of the receiver transformed to integers."
asNumber CharacterArray 1 '123' asInteger "Answer the number created by interpreting the receiver as the string representation of a number. First remove any leading separators."
asLowercase CharacterArray 3 '12abAB' asLowercase "Answer a string made up from the receiver whose characters are all lowercase."
asUppercase CharacterArray 3 '12abAB' asUppercase "Answer a string made up from the receiver whose characters are all uppercase."
class Object 1 '12abAB' class "Answer the object which is the receiver's class."
dropVowels String 1 '12abAB' dropVowels No comment available, guess from the name, what it does
inspect Object 1 anObject inspect "Create and schedule an Inspector in which the user can examine the receiver's variables."
isString String 2 'aString' isString "Answer true that the receiver is a String."
isString Object 2 anObject isString "Coerce String to true and everything else to false. String overrides with ^true."
reverse SequenceableCollection. 2   "Answer with a new sequential collection with its elements in the opposite order."
size ByteString 20 '12abAB' size "Answer the number of indexable fields in the receiver. This value is the same as the largest legal subscript."

Question 2.
Which Message selector should not be in the table. Go to answer
After the next exercise, you will learn why you need to know the class(es) a message selector can work with.
Go to Answer 2

 


Question 3.
From the table above: Which message selectors are keyword messages, and which are binary?
Go to Answer 3

 


The information shown in the above table was obtained by using the class browser, how to do this is explained in Tutorial 16.
This is the type of information required, in order to select a message to use, therefore it is provided above for use in the following exercise.

 


Exercise. 2
In the Workspace experiment by sending messages from the table above, to the receivers listed in the table below.
Your aim is to make the required answer, appear in the answer pane.
When you have done this, fill in the Enter message expression column with the required message expression in the table below

 

  Receiver Enter message expression To produce this answer Comments
E.g. 'abcd' 'abcd' at: 3 'c' By experimentation in the workspace you would have discovered that when evaluated
'abcd' at: 3
answers 'c'
a 'Hello World'   'HELLO WORLD'  
b 'Hello World'   'dlroW olleH'  
c 'Hello World'   'Hll Wrld'  
d 'run'   'ran' The answer I expect you to receive is $a "16r0061"
The solution requires the use of a local variable, which have not been discussed so far.
e 'Hello World'   Character space  
f 'Hello World'   true  
g 'Hello'   'Hello World' You will need to supply a string as the argument
h 'Hello'   ByteString  
i 'Hello'   an inspector window  
j 'Hello World'   'hello world'  
k 'Hello'   5 The number of characters in the string
l '78.9'   78.9  
m '78.9'   78 Press cancel button on Exception error window. The solution requires the use of sending multiple messages.
n $N   78 Demonstrates the correct use of message sent to a Character rather than ByteString
Go to solution 2a

 

 

Question 4 Because
'78.9' asNumber answered with 78.9
You may have thought that '78.9' asInteger would have answered with 78.
Why does
'78.9' asInteger
produce an exception notifier.

 

Go to Answer 4

 


You may have thought that
'run' at: 2 put: $a
would have answered with 'ran'

 

The comment "Store the Character in the field of the receiver indicated by the index. Fail if the index is not an Integer or is out of bounds, or if the argument is not a Character, or if the code of aCharacter does not fit in one byte." Does tend to suggest this, but what is missing from he comment is what the method answers with.

 

In the next tutorial, tutorial 4, we will have a look at this method.
Note this Tutorial should be available shortly

| Previous Tutorial 2. | Next Tutorial 12. Decisions and Loops | Top of Page |


Answers


Answer 1. In Smalltalk a string starts and ends with a single quote. E.g. ' Hello World', and a comment is placed in double quotes " This is a comment "
Return to Question 1.

 

 



Answer 2.
The message selector asInteger should not be in the table. The method asInteger is found in the class Character, which is in the Magnitude class hierarchy.

 

Return to Question 2

 

 



Answer 3. HELLO WORLD
at: and at:put: are keyword message selectors.
, (Comma) is a binary message selector.
All the rest are unary message selectors.

 

Return to Question 3

 

 



Answer 4.
Although asInteger is a method in the classes Number, Integer and Character.
Instances of ByteString do not have the message asInteger in their protocol.
Therefore a semantic error occurred, resulting in the Exception notifier.
Return to Question 4

 

Top of Page


Solutions to Exercises


Solution to Ex 1d.
Object 
        Collection
                SequenceableCollection
                        ArrayedCollection
                                CharacterArray
                                         String
                                                ByteEncodedString
                                                       ByteString

Continue with next section

 


Solution 2a.
  Receiver Enter message expression To produce this answer Comments
E.g. 'abcd' 'abcd' at: 3 'c' By experimentation in the workspace you would have discovered that when evaluated
'abcd' at: 3
answers 3
a 'Hello World' 'Hello World' asUppercase 'HELLO WORLD'  
b 'Hello World' 'Hello World' reverse 'dlroW olleH'  
c 'Hello World' 'Hello World' dropVowels 'Hll Wrld'  
d 'run' 'run' at: 2 put: 'a' An exception message. This answer will be explained.
e 'Hello World' 'Hello World' at: 6 ' '  
f 'Hello World' 'Hello World' isString true  
g 'Hello' 'Hello' , ' World' 'Hello World' You will need to supply a string as an argument
h 'Hello' 'Hello' class ByteString  
i 'Hello' 'Hello' inspect an inspector window  
j 'Hello World' 'Hello World' asLowercase 'hello world'  
k 'Hello' 'Hello' size 5 The number of characters in the string
l '78.9' '78.9' asNumber 78.9  
m '78.9' '78.9' asInteger An Exception notifier Try this, then press the Cancel button. An explanation will follow.
m '78.9' '78.9' asNumber asInteger 78 See Multiple messages that follow.
n $N $N asInteger 78 The ASCII decimal code value

Continue

 

| Previous Tutorial 2. | Next Tutorial 12. Decisions and Loops | Top of Page |

 

Top of Page.

 

Sites by John McGuinn . HTML and Web Design | C Programming

Leeds & the UK Tourist Information & guide my home town

Relax in the sun.

Benidorm   Tenerife   San Marino apartments to rent

Holidays and Short Breaks     Manchester Airport

Leeds my home town City of Leeds information  Leeds and Bradford International Airport

AireWeb Web Design
Leeds Web Design Web Designers Hosting Domain names Web site Promotion

Copyright © John McGuinn 2000 - 04