Establishing secure connection… Loading editor… Preparing document…
Navigation

Fill and Sign the Blumberg T 186 Lease Form

Fill and Sign the Blumberg T 186 Lease Form

How it works

Open the document and fill out all its fields.
Apply your legally-binding eSignature.
Save and invite other recipients to sign it.

Rate template

4.8
67 votes
1. Introduction to object-orientation. There is little that is new in object-oriented software development. Its main ideas have been around for over two decades since the development of the programming languages Simula and Smalltalk. It is now a well-established technology, and its advantages are well understood. If only we could learn to use it well, we should be able to build high quality software systems which are modularised and decentralised; are factored around data rather than processes; are built using existing well-tested components; promote the development of new components; are easy to understand and maintain; are better able to withstand change; allow a relatively seamless transition from analysis through to design and implementation Older approaches are however still very much in evidence, and most readers of this text are likely to have had some exposure to more traditional approaches to software development. This chapter begins therefore by comparing the process-oriented and object-oriented approaches to software development. It also provides an introduction to the main concepts of objectorientation, and concludes with an introduction to the Eiffel programming philosophy and language. 1.1 Process-oriented software development: a text formatter Process or functional approaches have dominated software design since the beginning of computing. Systems developed in this way are conventionally subdivided into relatively abstract sub-functions, which may be further subdivided into sub-functions recursively until, at the bottom of the hierarchy, there are the primitive operations which perform the actual computation. Such an approach was particularly well suited to designing systems for the commercial batch applications for which the COBOL language has been primarily used. It was also well suited to the design of text processing systems 1 Eiffel Object-Oriented Programming 2 such as compilers and formatters. As an example we may take a text processor which which has a file of text with embedded print directives as its input, and a print file with appropriate paragraphing and indentation as output, as shown in figure 1. Text File Process Text Print File figure 1 The process involves transforming the information read from the input file into that suitable for the output file. Such systems are typically decomposed as shown in figure 2. Process Text 1.1 1.2 Do Initial Process 1.3 Do Main Process Do End Process figure 2 The above abstract solution indicates the sequence of operations: sub-processes are executed from left to right. The sub-processes could be subroutines, or in larger systems they could be separately compiled programs. Initial processing conventionally includes the initialisation of data items and the opening of files. End processing consists mainly of closing the files, and possibly the output of summary totals if required - e.g. number of words, number of lines, number of pages and so on. The main process requires an iteration or loop which indicates that each line of the source text must be processed until the end of the source file is reached: 1.2 Main_Process do until End_Text_file 1.2.1 Read Line of Text Introduction to object-orientation 1.2.2 Process Line of Text end -- Do Until end Main Process The above algorithm also indicates that the sub-processes Read Line of Text and Process Line of Text must at some stage be refined. A possible solution for the second is shown below: 1.2.2 Process Line of Text if first char is a format character then Process Format String end - - if write text to file end Process Line of Text This would then require further refinement of Process Format String e.g. /P/ might indicate a new page, /8/ might indicate indent 8 spaces and so on. As already indicated this problem is a relatively simple one, which is easily solved using a process-oriented approach. In order to illustrate the difference between the two approachs, the next section solves the same problem using an object-oriented approach. 1.2 An object-oriented approach to developing a text formatter An OO developer would take a totally different approach, and would seek to identify objects or classes of object in the system. (For the moment no distinction will be made between a class and an object - see section 1.4) Obvious candidates in this case would be text file print file Less obvious might be line of text format string In addition a controller, called TEXT_FORMATTER, might be specified. While not essential, it is frequently useful to have such an object. The application, consisting of five objects, could be described as follows: TEXT_FORMATTER sends a message to TEXT_FILE asking it for a line of characters. TEXT_FILE reads a line of characters from disk, and passes a line of characters back to TEXT_FORMATTER; TEXT_FORMATTER creates a LINE_OF_TEXT from the line of characters, and asks the LINE_OF_TEXT to send itself to PRINT_FILE; the LINE_OF_TEXT checks whether it contains format 3 Eiffel Object-Oriented Programming characters, and if it does then creates a FORMAT_STRING and asks it to send itself to PRINT_FILE; it then sends its character string to PRINT_FILE, and returns control to TEXT_FORMATTER. TEXT-FORMATTER repeats the process until TEXT-FILE can provide no more lines of text. The result of approaching development in this way is to decompose a system into units based not on function, but on data. The text file and the print file are obviously data structures, the line of text is likewise a sequence of characters, which may be simply a string of printable characters such as This is a line of text or may include a format string /8/ which is a sequence of characters enclosed by "/", which have a particular meaning within the context of our system. The only object which is not a data structure is the controller, TEXT_FORMATTER. It could of course be eliminated, in which case TEXT_FILE or PRINT_FILE would become the controller. Some designers might argue about the need for FORMAT_STRING, which is also not essential. Clearly there are losses in efficiency in having such an object, but there are also potential maintenance gains. If, for example, an additional set of allowable embedded commands was introduced, the only component which would need to be amended would be FORMAT_STRING. The ability to isolate the effects of change is one of the essentials of developing maintainable software. The relationships between the objects may be analysed as follows: Object Collaborators TEXT_FORMATTER SOURCE-FILE PRINT-FILE LINE_OF_TEXT SOURCE_FILE PRINT_FILE LINE_OF_TEXT FORMAT_STRING FORMAT_STRING PRINT_FILE It can be seen that the two file handling objects are purely passive: they respond only to calls, and need no knowledge of any other objects within the system. If TEXT_FORMATTER were eliminated, and SOURCE_FILE or PRINT_FILE to be made the controller, then the one selected would need to collaborate with other objects. 4 Introduction to object-orientation One advantage of this approach is that each object could be implemented, compiled and tested separately, even by different programmers, although for such a small system this would be most unlikely. The tasks required to produce a formatted print file would be distributed in the object-oriented system as indicated below: Object Task TEXT_FILE opens file closes file reads a line of characters from disk passes string of characters back to caller PRINT_FILE opens file closes file writes to disk a character string passed in by caller LINE_OF_TEXT separates into format string and character string creates FORMAT_STRING asks FORMAT_STRING to write itself to PRINT_FILE sends its own character string to PRINT_FILE FORMAT_STRING sends appropriate characters (spaces, control characters) to PRINT_FILE TEXT_FORMATTER asks files to open themselves asks files to close themselves controls process The development of the last object would be done later than in the processoriented approach illustrated earlier. TEXT_FORMATTER might however, be used as a harness to test each object in turn as it was completed. Once testing of separate objects was finished, the code required to control the system could then be inserted in TEXT_FORMATTER: ask files to open themselves do until no more lines of text to process get string of characters from SOURCE-FILE ask LINE_OF_TEXT to print itself on PRINT_FILE end -- do until ask files to close themselves 5 Eiffel Object-Oriented Programming Should it be required, it would be relatively simple to dispense with TEXT_FORMATTER, and to transfer this small amount of code to one or the other of the file objects as previously suggested. 1.3 Object-oriented and process-oriented approaches compared The difference between an object-oriented and a more conventional top down approach may be summarised as follows: 1. a conventional developer divides a system into program units corresponding to the operations or processes which it must perform; an OO developer decomposes, or modularises, systems around objects, which are a combination of data and functionality; 2. a conventional developer views a system as a sequence of operations; an OO developer views a system primarily as a collection of objects which collaborate with each other to perform a set of tasks; 3. in a conventional top-down system a sub-process should be called only by a single higher level process; within an OO system an object may respond to requests for services from any other object; 4. whilst sequence is not important to an OO developer, the state of an object at the point when it is requested to perform some action is a concern: it may be necessary to stipulate what conditions must hold at the time when an object is asked to perform an action. For example, going back to the text formatter, it might be agreed that TEXTE_FILE should not be asked to produce a line of text if it is empty - the caller would be required to check that TEXT_FILE could supply a LINE_OF_TEXT before asking it to do so. This is known as a precondition, and is fundamental to Eiffel programming as will be shown later. Finally, it should be emphasised that object-oriented techniques are particularly suited to modern interactive systems, as will be illustrated by the introduction of a second example, a word processor. The process-oriented approach is less satisfactory for designing event-driven interactive systems which have no real top function, and no clearly defined sequence of operations. It would be difficult to define the top function of a word processor, which must simply wait for a user to press a key or to click a pointing device. 6 Introduction to object-orientation 7 A developer who wished to design a word processor would again begin by identifying the objects or classes in the system. Candidates for initial consideration would include menu text pane block of text text buffer file as shown in figure 3. Text Pane Menu Block of Text Load Save the final date will not be available for some time yet so whatever is done had better be done Cutthis is another way of saying that he is not ready Paste Quit File Text Buffer Components of a word processor figure 3 Further investigation might eliminate some of the above, and might include one or two that have been overlooked. The application would for example need a mechanism to handle events - inputs from the keyboard and a mouse. This is system dependent however, and will not be discussed abstractly. Once a preliminary list of objects has been defined, the designer must then try to work out the role of each in the system. This process should expose redundancies and also gaps in the set of objects proposed. This involves questions such as what actions must this object be able to perform? what does it know? what data must it store? which other objects does it collaborate with? In practice some of the objects mentioned, such as MENU, would probably be available in the class library. The benefits of an OO approach in designing systems which involve graphical user interfaces ought to be fairly readily apparent : Eiffel Object-Oriented Programming the kinds of object defined above are likely to be common to many GUI applications; it is possible to build systems by reusing existing components, or to produce as a by-product well-tested components which may be reused in other applications; it is easier to make changes to a system designed around objects, such as pane, and menu - which are relatively stable - rather than functions such as 'cut and paste' , 'load file' and 'save as' which are less stable. Finally, as will be explained in the following section, in practice the OO developer would design classes of object rather than single objects. Rather than individual objects, classes such as TEXT_WINDOW and MENU would be used. This would for example make it relatively easy to have more than one window, each with its own menu. Without this capacity to create more than one object of the same class, the development of a multi-windowing word processor would be difficult to achieve. 1.4 Objects, Classes and Message Passing The basic ideas of an OO approach to are deceptively simple. The fundamental concepts are those of objects, classes and message passing: An object is: (i) an entity in the real world application being modelled or in the computer environment in which the application is being implemented; (ii) an instance of a class created at run time; it has state and behaviour. Objects interact by sending messages or requests to each other and sometimes to themselves. A class is a template from which objects may be created at run time. In most languages we design classes not objects. This allows us to instantiate more than one object of the same class when a system is executing. A conventional notation for describing classes of object is shown in figure 4. In the top sector the name of the class is given. In the middle sector the data 8 Introduction to object-orientation 9 variables that are used to store the state of an object of that class are listed, and in the bottom sector the services which an object of that class offers to a client are listed. The terminology for the last sector varies - there is no standard terminology throughout the OO community - sometimes it may be referred to as the methods of a class, or as the messages to which an object of a class will respond. In Eiffel the services are known as routines, and the messages are known as calls. name data STATE services BEHAVIOUR figure 4 The notation is used in figure 5 to model LINE_OF_TEXT, which was described in the first example above. Each object of this class would contain a single data item, a string of characters, such as "Do not go gently into that good night" or "/8/ Come into the garden Maud" and would need to respond to one message only, to print itself on a file: Eiffel Object-Oriented Programming LINE_OF_TEXT character_string print_on_file figure 5 The tasks which an object of this class is required to perform: separate into format string and character string creation of FORMAT_STRING message to FORMAT_STRING to write itself to PRINT_FILE sending of its own character string to PRINT_FILE are not services offered to other objects in the system; they are auxiliary actions necessary to enable a LINE_OF_TEXT to carry out the request: print yourself on file. An external caller knows nothing about FORMAT_STRING, and would not be able to request LINE_OF_TEXT to carry out any of the first three actions.This logically leads on to the concept of information hiding which is covered in the next section. 1.5 Information hiding A key idea of object-oriented development is that of abstraction: hiding implementation details from the clients of a class. It is useful to distinguish between the interface to a class, and its internal mechanisms, between the public part of a class, and its hidden or private part. This distinction is important, because it allows the internal mechanisms of a class to be protected from outside interference, and at the same time allows us to provide a more abstract, simpler view of a class. To return once more to class LINE_OF_TEXT: externally it may be viewed as consisting of simply one service, and one data item; this is all that the caller needs to know. The implementor, however, will need a different, less 10 Introduction to object-orientation abstract view: to know about FORMAT_STRING and PRINT_FILE, about which the caller of LINE_OF_TEXT need have no knowledge. A real world analogy may be used to illustrate this: a car There are at least two views of a car: 1. that of the driver who controls it through the interface supplied: control panel, steering wheel, brakes, accelerator pedal; 2. that of the mechanic (who may also be the owner and sometime driver of the car) who monitors the collection of components hidden under the bonnet whose proper functioning are necessary to provide the services required by the driver; It is not necessary for a driver to have much knowledge of what exists under the bonnet, and it is thankfully not necessary to directly manipulate the axles, brake pads, carburettor, gear box and other components in order to drive a car. A simpler interface is provided. So it is with software components. All object-oriented environments should provide mechanisms which may be used to restrict access to data and behaviour and to provide an abstract external view of the facilities which a class makes available. The concepts of class, object, message passing and information hiding, which have now been introduced are fundamental to an understanding of object-orientation. The concept of inheritance must now be introduced. 1.6 Inheritance Inheritance is an important facility provided by all class based objectoriented languages. It is a mechanism which allows classes to be designed so that common behaviour and data may be factored out and implemented at a high level in a class hierarchy. The most general classes in the hierarchy are at and towards the top, and the most specialised classes are at the bottom. This is illustrated in figure 6. The root of the hierarchy is VEHICLE, an abstract class. LIGHT_VEHICLE and HEAVY_VEHICLE are also abstract: the reader would not normally say "I am going out to buy a light vehicle", but "I am going to buy a car" or "I am going to buy a van". There might be more than four actual classes, but classes such as HONDA, ROVER, MERCEDES, CHEVROLET would not be allowable. Like engine size, model, and year, these are attributes of a VEHICLE, not specialisations of CAR. 11 Eiffel Object-Oriented Programming 12 VEHICLE HEAVY VEHICLE LIGHT VEHICLE CAR VAN BUS LORRY Inheritance as specialisation figure 6 It should be noted that the relationship between a descendant class and an ancestor class is often described as an is-a or a is_a_kind_of relationship. In the above example we could say that a car is a light_vehicle, and a light_vehicle is a vehicle, but in each case the reverse is clearly not true: a light_vehicle is not a car. These ideas are explored further in chapter 9. As well as allowing the design of hierarchies of classes from scratch, an inheritance mechanism is frequently used to create a new class out of an existing class. This allows data and behaviour to be reused, as well as the addition and redefinition of data and behaviour in the new class. The basic idea of inheriting behavious can be illustrated by going back to the word-processor example. We might decide that a TEXT_PANE should be able to perform the following services for clients: open close scroll up scroll down insert n lines at relative position x,y delete n lines at position x,y save contents to file load contents from file copy from buffer copy to buffer move cursor to relative position x,y move cursor up/down move We might find that in our class library we have a class PANE, which fulfills most of the required functionality, but does not have facilities for the following: scroll up scroll down move cursor up/down/ save to buffer copy from buffer copy to buffer save contents to file load contents from file In this situation class TEXT_PANE could inherit from PANE, and the additional facilities required could be developed in the new class. The new Introduction to object-orientation 13 class would probably require data to keep track of the associated file and text buffer, and some new services. For the following services the code provided in PANE could be reused: open close move cursor to relative position x,y move insert n lines at relative position x,y delete n lines at position x,y The location of the services in the hierarchy is shown in figure 7. PANE TEXT_PANE open close move insert lines delete lines move cursor to x,y scroll-up scroll_down copy from buffer copy to buffer save to file load from file move cursor up/down Inheriting behaviour from PANE figure 7 The inheritance mechanism would allow any instance of class TEXT_PANE to provide the full list of services required, without rewriting or copying any code, and without making any alteration to PANE itself. If the class library did not provide a MENU, it would be possible to develop this also as a descendant of pane, as shown in figure 8. Eiffel Object-Oriented Programming PANE 14 open close move insert lines delete lines move cursor to x,y TEXT_PANE MENU initialise pop_up hide return selection Inheriting unsafe behaviour figure 8 In this case however, inheritance presents potential dangers; a user of MENU should be prevented from accessing the services displayed in bold face. In this situation the use of inheritance might not be the best solution, and the client relationship might be better. 1.7 The concept of client The concept of a client is rarely highlighted in texts on object-oriented programming. It is, however, an important part of object-oriented software development, and merits an early, albeit brief, introduction. A class may be said to be a client of another if it uses that class. The most common case is known as the has-a relationship: a VEHICLE has an engine, has a colour and has a manufacturer or make. It would be wrong to say that a VEHICLE is a kind of ENGINE, is a kind of COLOUR or is a kind of MAKE. Engine, wheel, colour and make are attributes of a VEHICLE, and VEHICLE is therefore a client of ENGINE, COLOUR and MAKE. Often the choice between an inheritance relationship and a client relationship is not as clear cut as this, as will be found in later chapters. This concludes the discussion of object-oriented concepts. The chapter concludes with a brief overview of the Eiffel language Introduction to object-orientation 1.8 An overview of the Eiffel Language This section is aimed largely at those with prior knowledge of objectorientation. The brevity of treatment means that those with less experience will find that much that follows will prove difficult on a first reading. It should, however, serve as a useful reference as the topics are covered in later chapters. Classes The modular unit is the class: we write classes and only classes. An Eiffel application is characterised by a structured collection of classes, one of which must be specified at compile time as the root class. Objects are not recognised as part of the syntax of Eiffel. An object is an instance of a class, created at run-time. Eiffel allows only two relationships between classes: the inheritance relationship and the client relationship. The syntax of the root class does not differ from that of any other class. It must have a creation routine, which contains the code which executes immediately a system is activated. Other classes may also have creation routines, which must be invoked when an instance of the class is created. Abstraction There is no separation between a class interface and a class implementation in Eiffel. An Eiffel environment should provide a tool to generate an interface (a short form), from an Eiffel source file. Eiffel supports information-hiding. All attributes are readonly. Both routines and attributes may be made private, or be made available to specific named client classes. Descendants may alter the external visibility of inherited features. 15 Eiffel Object-Oriented Programming Class Features An instance of a class has data, known as attributes, and behaviour, known as routines. Both attributes and routines are known as the features of a class. Each attribute has a defined class type. The Eiffel type system is based on the notion of class. Routines may return a result; the result-type is declared at compile time. Routines may have parameters; these are known as arguments in Eiffel. Eiffel supports only call by value, so that arguments may not be used to pass back a result. Each formal argument must be declared with a class type. Eiffel allows for the declaration of local variables within a routine; it does not support the nesting of routines. Eiffel supports recursion. Inheritance Inheritance in Eiffel is open: a class may not limit the facilities available to descendants, nor can it restrict certain facilities to specified descendant classes; such a facility would run counter to the emphasis on reusability and to Meyer's 'open and closed' philosophy. Facilities are provided for adapting inherited features: these include renaming, redefinition, changing visibility (re-export) and undefinition (making a feature deferred). Eiffel provides for multiple and repeated inheritance, for deferred (or abstract) classes and for generic classes. Instructions In Eiffel statements are known as instructions. 16 Introduction to object-orientation Eiffel enforces the message-passing metaphor: it is not possible to include a file of arbitrary functions or procedures, and every call to a routine must have a target. When the current object is the target, the target may be implicit, but it can be made explicit by using the identifier Current. Except in the case of the basic types, assignment is pointer asignment, and a test for comparison of two objects yields true only when an object is compared with itself. Eiffel provides a small set of control instructions: Loop Conditional Multi-branch Control instructions may be nested. Library facilities Eiffel is a small language, and many facilities, including input-output, arithmetic operators and relational operators (except for the '=' operator) are provided in the class libraries rather than as part of the language. All classes in Eiffel inherit from class ANY which inherits from GENERAL. This class includes a number of standard routines including those used for copying and comparing objects which may be used by instances of any class. Standard classes in Eiffel (INTEGER, REAL, CHARACTER DOUBLE) are implemented as expanded (non-reference) types. The language itself has no data structuring facilities other than the class itself. Standard data structures (ARRAY, LIST), and STRING, are supplied in class libraries. Memory management 17 Eiffel Object-Oriented Programming By default Eiffel classes are implemented as references. Instances must therefore be explicitly allocated memory by the programmer using a creation instruction. No deallocation of memory is required. All Eiffel systems include a garbage collector which keeps track of the memory allocated to a system during its execution, and reclaims memory no longer required. This is consistent with the desire to build a high level abstract language: in such an environment it is inappropriate to require programmers to manage memory. Design by contract The use of assertions is central to Eiffel programming. Assertions allow system builders and programmers to reason about the behaviour of instances of classes; they serve as an important tool in specifying classes, documenting classes, and, because of the run-time support provided by all Eiffel systems, in testing and debugging classes. Preconditions define what must be true on entry to a routine, postconditions define what is guaranteed to be true on exit from a routine. There are also class and loop invariants, loop variants, and facilities to aid debugging and to handle exceptions. Exercises 1. Make notes on each of the following: attribute, service, object, class, message-passing , information hiding. 2. Identify the main uses of inheritance covered in the chapter. Why might it be unsafe to make MENU inherit from PANE? 3. An information system is being developed to store course results for a University Department. The department has a number of courses. Each student is on a single course. Each course has a full-time and part-time variant, and is composed of a collection of modules. Each student takes a collection of modules each semester. A module is taught by a lecturer and is taken by a collection of 18 Introduction to object-orientation students. Each student has a mark for each module taken. The following classes have been identified: DEPARTMENT COURSE MODULE STUDENT LECTURER MARK COLLECTION FULL-TIME PART_TIME a) A model is being constructed from the above description. Which of the following seem correct? i) course: has a collection of students; has a lecturer; has a collection of modules is a collection of modules; ii ) part-time course has a course; iii) full-time course is a course; iv) a student has a collection of modules; v) student is a collection of marks; vi)department : is a collection of students; is collection of courses has a collection of students is a collection of lecturers b) class MODULE is required to fulfill the following services: display the lecturer name is lecturer Y responsible for this module? display the collection of students and their marks is student X taking this module? what is the mark for student X on this module? what is the average mark of this module? DEPARTMENT has a collection of COURSES. In order to answer a request such as, print out the results for student Y , might require the following scenario: "For each course in the collection, DEPARTMENT asks the COURSE whether student X is on the course; if the answer is yes then DEPARTMENT asks the COURSE to display X's marks. For each module in the collection, COURSE asks the MODULE if X is taking the module; if the answer is yes then COURSE asks the MODULE for the mark, and when it receives it, displays it on the screen." i)Work out a suitable list of services for class COURSE ii) Write scenarios showing how class DEPARTMENTcould use the services provided by COURSE and MODULE to achieve the following how many courses do you have? what is the average mark for module X? what is the average mark for student Y? display the list of marks for module Z. display the average marks for the modules taught by lecturer XYZ. 19 2. Writing a Simple Class in Eiffel The reader should already have gathered the following from chapter 1: a class may be defined as a template from which objects may be created; in Eiffel a class is also the basic program unit: we write classes, and only classes; every Eiffel application must have a single root class; conceptually the application may be thought of as an object of this class the root class must include a creation routine which is executed when a system is loaded; other classes may or may not have creation routines. This chapter begins with a simple root class, which the reader is encouraged to enter and compile, and continues with exploration of inputoutput in Eiffel. The example root class is used to introduce a number of basic concepts, including attributes, call instructions, assignment instructions, and type. The most difficult material covered is likely to be that on reference types in section 2.8, to which an inexperienced reader may wish to return at a later stage. 2.1 The syntax of an Eiffel Class The syntax of an Eiffel class is shown in very simplified form below. class [ creation ] feature {routines | attributes } end In our notation the special symbols used, known as meta-symbols, have the following meaning: < > contains a user-defined name { } an iteration indicates that the constructs within the brackets occur 0 or more times 19 Eiffel Object-Oriented Programming | indicates an alternative, either the construct to the left or the right must be selected [ ] indicates an option All keywords are in bold type, and user defined names are in italics. The definition above indicates that a class begins with the keyword, class, and is terminated by end. The class name is a user-defined name. After the class heading there is an optional creation-part, in which the name of the creation routine is specified. In some cases more than one creation routine may be specified, but this is relatively unusual. A class feature may be either an attribute or a routine. Class features are introduced by the keyword feature which may appear more than once in a class. As a first example we shall look at an Eiffel root class which produces output on the screen. This class, which is called SIMPLE, is extended in the early chapters of the book to illustrate the various Eiffel constructs. class SIMPLE; creation test feature test is -- outputs a string to the screen do io.put_string("This is my first Eiffel class"); io.put_new_line end -- test end -- SIMPLE Example 2.1 An Eiffel Root Class A few additional points may be made about the above class: 1. Class names are by convention written in uppercase. The compiler, however, is not case sensitive, and so makes no distinction between "Simple", "SIMPLE", "simple" or even "siMPle. Both "SIMPLE" and "test" are userdefined names. Keywords may not be chosen as user-defined names. 2. The above class contains three comments. Comments in Eiffel are preceded by a double hyphen : -- This is a comment Comments are intended to make the class text more readable; they are ignored by the compiler. It is a sensible idea to use comments to write the name of a class or a routine at the end, as shown in the example above. 3. The above class has a single feature, a routine, test. Usually a class will have several features. 20 Writing a Simple Class in Eiffel 4. The routine test is specified as the creation routine. When the class is executed, the body of test - the instructions written between the keywords do and end - are executed. In this case there are two instructions only, and both are calls to io. When SIMPLE is compiled , linked and executed the message This is my first Eiffel class should duly appear. 2.2 The Eiffel environment In order to execute class SIMPLE, the reader needs to know how to enter text using the editor provided in the environment being used, and how to invoke the compiler. It is also necessary to know a little about ACE files. As already indicated, class SIMPLE is intended to be a root class, that is to say that it may be compiled, linked and executed on its own, with support from the kernel library. In order to try the above example, the source code should be entered using an appropriate text editor, and should be saved in a file with a .e suffix, which is used for all Eiffel source files. The programmer may now call the compiler. In SmallEiffel the following would be entered: compile simple SmallEiffel assumes that the creation routine is called make, if not then the name of the creation routine must be specified. Users of ISE Eiffel will need to edit the default ACE file. The compiler checks SIMPLE against the rules of Eiffel. Provided no errors have been made, the compiler generates C code, it then calls the C compiler to create object code, and finally calls the linker to create an executable file. The application may then be run either by clicking on the appropriate icon, if using a graphic environment, or by entering the name of the executable, which was defined in the ACE as example1. The reader will notice that when SIMPLE is compiled, a number of other classes from the Eiffel library are required, and the executable file produced by the linker is rather large for a system that does so little. This is because any Eiffel application, however small, requires a minimum of support from the kernel classes. The size of an executable does not therefore increase significantly for larger systems. 2.3 Call instructions The call instruction is a fundamental of object-oriented programming and of Eiffel. It is a request by one object for action from another. In Eiffel it takes the form of a call to a routine defined in a client class. The first of the calls has three components, as shown in figure 1. 21 Eiffel Object-Oriented Programming io target put_string "This is my first Eiffel Class" routine argument figure 1 The second call is similar, but has no argument. It simply moves the cursor to the next line on the screen. A call must by definition have a caller as well as a target. In the above cases the caller is an instance of the root class SIMPLE, and the target is io, which is an instance of class STD_FILES, which may be accessed by an instance of any class (see section 2.4). Sometimes an object may call itself. In such cases the target is implied, and a call consists solely of the routine name and any parameters required. The predefined identier Current may be used to make the target explicit. 2.4 I-O in Eiffel Basic input-output facilities in Eiffel are provided by the class library. To do basic input and output using the screen and keyboard in Eiffel we must, as shown already, make a call to an instance of class STD_FILES, or in the case of SmallEiffel, STD_INPUT_OUTPUT. In most cases the call is made to io, io.put_string; io.read_integer Io is defined in class GENERAL. Each class in an Eiffel system automatically inherits from ANY, which itself inherits from PLATFORM, which inherits from GENERAL. In most ISE implementations GENERAL should contain the following entry: io :STD_FILES is once !!Result end -- io and in SmallEiffel io : STD_INPUT_OUTPUT is once !!Result end -- io which returns a shared copy of io. The following table lists the basic facilities available for input-output provided. IO in Eiffel 22 Writing a Simple Class in Eiffel 23 Attributes (Data) last_character:CHARACTER last_integer:INTEGER last_real:REAL last_string:STRING last_boolean :BOOLEAN Output routines put_character(c:CHARACTER) put_integer(i:INTEGER) put_real(r:REAL) put_string(s:STRING) put_boolean(b:BOOLEAN) put_new_line Input routines read_character read_integer read_real read_line read_word read_boolean -- result stored in last_string -- result stored in last_string The above features have been divided into three categories. The last cataegory defines the operations used for input, the second category defines those used for output. The first category defines the attributes or state variables, which are used to store the last item read from the keyboard by the corresponding input routine. So for example io.read_character takes a character from the keyboard and transfers it to last_character. To access last_character we must refer to it as io. last_character Some readers may have noted that Eiffel uses the same dot notation for accessing a routine and an attribute. More experienced programmers may wonder why input in Eiffel is handled in this way. It would have been possible to have implemented last_character as a routine which read the keyboard and returned the character immediately to the calling routine. The use of a sideeffect in a function is generally considered to be bad practice however, and this solution was deliberately rejected by the language designer. For similar reasons Eiffel provides no call by reference or variable parameters. Readers who wish to pursue this further are recommended to read Meyer (1988) for the discussion of side effects in functions. It may be noted that there is no state variable for. This routine reads the keyboard until it finds the newline character; it is not required to return Eiffel Object-Oriented Programming anything, and so has no associated variable. It is used simply to move the cursor so that subsequent input-output is on the next line. 2.5 The assignment instruction We have already seen how a string of characters may be displayed on the screen using put_string. This section illustrates the use of additional i-o facilities and introduces another fundamental instruction, the assignment. In the example 2.2 the body of the routine test, contains a sequence of instructions, which display the product of two integers on the screen. In addition to calls to io, the routine test now contains two assignment instructions. class SIMPLE; creation test feature first, second :INTEGER; test is -- inputs two integers and outputs their product do io.put_string("Enter an integer > "); io.read_integer; first := io.last_integer; io.putstring("Enter another integer > "); io.read_integer; second := io.last_integer; io.put_string("Product is : "); io.put_integer(first*second) end -- test end -- SIMPLE Example 2.2 Assignment instructions The assignment operator, ":=", should be viewed as a left pointing arrow first io.last_integer which indicates the direction of the data. When executed, it copies the contents of the right hand operand into the left hand operand. Thus in the example given in figure 2, the value 16 is copied from io.last_integer to the attribute first. 24 Writing a Simple Class in Eiffel Before assignment After Assignment 25 0 16 16 16 first io.last_integer figure 2 Readers with experience of other high level languages will have no difficulty with the concept of assignment, which is a core concept of imperative programming. In Eiffel and other O-O languages it is more complex however, as is shown in the fuller discussion of the semantics of assignment in chapter 6. 2.6 Class attributes In any object-oriented language a class is defined in terms of data and action. In Eiffel, both are known as class features. Action in an Eiffel class is encoded in routines (see chapter 4), and data items are known as attributes. This section shows how data is declared in an Eiffel class. In Eiffel, as in imperative languages, a variable is a user-defined name which refers to a location in the computer's read-write memory. As in other typed languages, an attribute must be declared with a type, as in example 2.2: first,second:INTEGER; Each variable attribute is allocated an area of memory sufficient to store an item of the attribute's type. The contents of the allocated area of memory may change during execution. So for example, the instruction first := second * 2; would calculate the result of the expression second * 2, and assigns that result to first - so that if second contained 20, then after execution first would contain 40. Sometimes it is useful to have a data item whose value is guaranteed to remain constant throughout the execution of a program. In Eiffel, constants are declared as shown below: feature message:STRING is " enter an integer > "; max_loan:REAL is 1500.00; months:INTEGER is 12; male:CHARACTER is 'm'; and may be accessed on a read only basis: io.put_string(message); io.put_real(max_loan); Eiffel Object-Oriented Programming io.put_integer(months); io.put_character(male); any_integer := months; The compiler would generate an error if a programmer tried to make message, max_loan, months or male the target of an assignment instruction. 2.7 Basic Types In Eiffel the concepts of class and type may for practical purposes be considered as identical. Every attribute declared in an Eiffel class must have a type. So also must every local variable, every routine argument and every function. The basic types available in the language include INTEGER BOOLEAN REAL CHARACTER DOUBLE The basic type DOUBLE is used to give double precision real numbers. Users who require high precision numbers may wish to use it instead of type REAL. To declare variables of the basic types the following notation is used: feature age:INTEGER; sex:CHARACTER; married:BOOLEAN; balance:REAL; Type indicates the range of values that may be assigned to a variable, it also indicates the operations that may be performed on it. For example we may multiply two integers, but we cannot multiply two chararacters. The following are examples of valid assignments that could be made to each of the attributes declared above: age := 23; sex := 'm'; married := true; balance := -23.76 As should already be apparent, the basic types are classes, and more advanced programmers may be able to gain an understanding of how to use them simply by studying the listings for classes COMPARABLE, NUMERIC, REAL, INTEGER, BOOLEAN and CHARACTER in the class library. In Eiffel. as in a number of programming languages, variables of each type are assigned a suitable default value. For Eiffel the initial values assigned are as follows: BOOLEAN false CHARACTER null character INTEGER zero REAL zero Chapter 3 discusses the basic types in more detail. 2.8 Reference types and creation instructions 26 Writing a Simple Class in Eiffel 27 Before the introduction to Eiffel types is concluded, it should be pointed out that there are two different kinds of type: expanded types and reference types. The Eiffel basic types are expanded types. Instances of expanded types contain the actual value or values, and memory for these is allocated by the compiler, as shown in figure 3. 97 an_object figure 3 Instances of reference types contain the addresses of the actual values, and the memory for the actual data must be allocated dynamically (figure 4). an_object address 97 memory allocated at run-time figure 4 Instances of reference types require explicit creation instructions, whereas the basic types require no such instructions and are given default values as indicated earlier. It is possible to develop expanded types, by using the heading, expanded class. All the examples developed in this text will, however, be reference types. This section concludes with an example of a creation instruction. Class STD_INPUT_OUTPUT is a reference type, and we may, if we wish, have our own copy of it, as opposed to the shared one inherited from class GENERAL. To do this we would declare it as with any other attribute: my_io: STD_FINPUT_OUTPUT but before using it we would need to ensure that memory was allocated to it by using an explicit creation instruction: !!my_io Unless this was done, the value of my_io would be Void, as depicted in figure 5, and any attempt to reference it by a call such as my_io.put_string("This is my Eiffel Object-Oriented Programming first Eiffel class") would result in a run-time error. The creation instruction therefore, is necessary in order to allocate memory at run-time to store the data. Void my_io figure 5 Finally, for completeness, it should be pointed out that if a reference class has a creation routine specified, then that routine must be invoked when an object of that class is created. So for example, take a class ANY_CLASS, which has a creation routine make specified. To create an_object of this class requires the following instruction !!an_object.make; if make required an argument then this would have to be included in the creation instruction, e.g. !!an_object.make(100) 2.9 Strings Type STRING in Eiffel is not a basic type, but is a special type in the Eiffel system. It is, like STD_FILES a reference type. Strings are denoted in the class source text by using double quotes: "This is a string". Examples of their use as output and as constants io.putstring("This is my first Eiffel class") message:STRING is " enter an integer > "; have already been encountered. It is also possible to declare variables of type STRING name:STRING to input strings, and to make assignments to variable attributes of type STRING. io.readstring; name := "Mel Giedroyc" It is also possible to use some of the relational operators to compare two strings. Full treatment of this and other aspects of string handling is given in chapter 7. 2.10 Special characters 28 Writing a Simple Class in Eiffel A number of special characters may be used in strings. The most useful of these is perhaps the new line character, which may be appended to a string io.putstring("This is a string%N"); This would ensure that subsequent input-output was on the next line, and so would remove the need to make a separate call to the new_line routine. The use of the '%' character therefore, plays a special role in Eiffel. If this character is to be displayed, it needs to be entered twice: io.putstring("50% %"); Further examples of its use are, io.putstring("%"This is in quotes%""); which would produce the output "This is in quotes" and %' which may be used to assign the single quotation mark to a character variable: aChar := '% ''; and aChar := '%U'; to assign a null character to a character variable. A full list of special characters is given in the appendix. 2.11User-defined names In any programming language a programmer must select names for variables and routines. These should be as meaningful as possible, to aid readability and maintenance of the program, by the author and by subsequent programmers. This is important for all programming, and especially for object-oriented programming which aims to produce reusable, quality code. The reader is recommended to look at the Eiffel class libraries as good models of clarity and consistency. The rules for forming identifiers in Eiffel are designed to aid the use of sensible names. Identifiers must begin with a letter, and may include digits and the underscore character. There is no limit on length, and programmers are encouraged not to shorten names artificially.The following are all valid: test test5 arithmetic_test final_year_results The convention used by Smalltalk programmers of denoting components of an identifier by an upper-case character is discouraged within the Eiffel community. Although it is legal to write identifiers such as arithmeticTest and finalYearResults, the use of the underscore character to separate component words is preferred. 2.12 Reserved words Like all programming languages, Eiffel uses some words for special purposes. These words may not be used as identifiers. There are two categories of reserved word: 29 Eiffel Object-Oriented Programming 30 1. Keywords 2. Predefined Names Keywords are in this text written in bold face, according to convention. The ones already introduced include class, feature, do, end. Key words are by convention always written in lower case although, as mentioned earlier, Eiffel is not case sensitive. Predefined names include the names of special types, such as INTEGER. Current, which was introduced earlier in the chapter as the target in cases of self-reference, is also a predefined name. The full list of keywords and predefined names is given in the appendix. 2.13 Special symbols A number of special symbols are used in the language. The text has already introduced the assignment operator, the single quotation marks used to delimit characters and the double quotation mark used to delimit strings.The reader is again referred to the appendix for a full list. Exercises 1. The following concepts have been introduced in this chapter. The reader is recommended to make notes on each : root class creation routine feature attribute call instruction argument assignment instruction constant type 2.Examine the contents of the kernel class library, particularly the universal classes GENERAL, PLATFORM and ANY, and at STD_FILES. 3. Each of the following amendments to class SIMPLE will produce compiler errors; some or all should be tried by those inexperienced in using compilers. Note the error messages produced in each case: i) declare an attribute of type CHARACTER; try to perform illegal operations on it (multiplication, addition etc) and to assign it to an integer; ii)change the spelling of INTEGER to INTERGER iii) change the name of the routine test to start, but do not alter the entry after creation. iv) delete the keyword do iv) delete the keyword end which terminates the creation routine v) delete the target of one of the calls vi) insert a space between the : and the = of the := operator 4. Amend class SIMPLE so that it prompts a user for information as shown below: Writing a Simple Class in Eiffel what is your name (STRING) what is your age? (INTEGER) what is your gender? (CHARACTER) are you married? (BOOLEAN) what is your salary? (REAL) Use constant attributes to define the messages that prompt the user for input. Use variable attributes to store the information read from the keyboard. At the end of the input sequence, display the information on the screen. Precede each field with a suitable label, e.g. Name: Liz McShane Age: 43 5. a)Amend example 2.2 as follows, noting what happens when the application is executed on each occasion: i) declare my_io as shown in section 2.8 and try to use it to output an integer to the screen without any creation instruction; ii) repeat, i) this time using a creation instruction on my_io iii) use a creation instruction on the integer attribute first; inspect the contents of first using put_integer both before and after the creation instruction; b) Consider the following: What is the effect of using a creation instruction on an attribute of a basic type? Why is it necessary to use an explicit creation instruction for reference types? 31 3. Eiffel Basic Types The previous chapter has already introduced the basic types supported by Eiffel. This chapter provides examples of operations that may be performed on attributes of the basic types. First, however, it provides an introduction to the concept of type. 3.1 Type checking Type checking is the process which allows the compiler to ensure that a data item is used correctly. To enable this to happen, a programmer must in a typed language such as Eiffel, associate a variable with a type: age : INTEGER; Typing cannot guarantee the correctness of a piece of software, but its presence puts restrictions on what a programmer may do, and allows the compiler to detect a set of errors which would otherwise go undetected and would lead either to run-time errors or to incorrect results. In Eiffel, as in other typed languages, it is not allowable to assign a value of one type to an attribute of another, so age := 'B' would not be allowable; if it were then consider the results of trying to perform an arithmetic operation on age, for example io.putint(age + 1); which would at best yield an indeterminate result. In a typed language a programmer is also prevented from mixing values of different types in an expression, so that 25 + 'B' would not be an allowable expression. Typing produces problems for object-oriented languages. In typed object-oriented languages the rules for assignment have to be slightly relaxed to take account of inheritance. In such languages we have to differentiate between the static type of an entity, which is the type that it is associated with at compile time, and the dynamic type, which is the type of the object to which it is attached at run-time. This topic is covered in more detail in chapter 9. In the case of the Eiffel basic types, however, the rule that an expression of type t can be assigned only to a target of type t must be adhered to, with one exception, which is discussed in the next section. 3.2 Operations on numeric types The most important numeric types are REAL and INTEGER. For variables of these types the following operators are available: REAL and INTEGER + plus minus // \\ INTEGER only integer division remainder after integer division 32 Eiffel Basic Types * / ^ 33 multiply divide raise to power // and \\ may be used only with integer operands. For example 14 // 5 and 14 \\ 5 are valid, and would yield the results 2 and 4 respectively, whereas 14.5 // 2 and 14 // 2.5 would not be allowed since in each case one of the operands is a real number. The / sign may however, be used with integers, but would yield a result of type REAL. So that 15 / 2 would yield 7.5 whereas 15 // 2 would yield 7. It would of course not be allowable to assign an expression which used the / sign to an integer variable, even if the operands were each of type INTEGER: an_int := an_int / 2 Eiffel does however allow us to assign an INTEGER expression to a variable of type REAL, since every integer is part of the set of REAL numbers. When more than one operator is used in an expression then the order in which each is evaluated depends on the rules of precedence, for example 5+3 // 2 yields 6, not 4, as a casual reading might suggest. But the result of 4 could be obtained by the use of brackets to override the operator precedence: (5+3)//2 Precedence is as follows: High precedence ( ) ^ * / + Low precedence // \\ These operations can now be illustrated in an example. A new feature, the routine, do_simple_arithmetic, is to be inserted in class SIMPLE as shown in example 3.1. class SIMPLE -- This class has been amended to demonstrate -- the use of arithmetic operators creation test feature first,second:INTEGER; do_simple_arithmetic is -- new routine; body still to be added do end -- do simple arithmetic Eiffel Object-Oriented Programming34 test is do ............. ............. do_simple_arithmetic; end -- test end -- SIMPLE Example 3.1 Adding a new routine to SIMPLE Note the single instruction added to the creation routine, test, which consists of a call to do_simple_arithmetic. This is a case of self-reference: the target of the call is also the sender. The target could have been made explicit: Current.do_simple_arithmetic The full code for the new routine is shown in example 3.2. do_simple_arithmetic is do io.put_real(first + second / 12.5); io.put_real((first+second) / 12.5); io.put_integer(first+second^3); io.put_integer((first+second)^3); io.put_real(first / second); io.put_integer(first // second); io.putint(first \\ second); io.put_integer(first+second // first -5); io.put_integer(first+second // (first -5)); first := first^3 +2 * second; io.put_integer(first); end -- do simple arithmetic Example 3.2 Body of new arithmetic routine The user may compile and execute class SIMPLE. If the values 10 and 30 are entered then the the sequence of values output should be as follows: 12.4 3.2 27010 64000 0 10 8 16 The following points should be noted from example 3.2: 0.3333 1060 1. The use of put_real instead of io.put_integer when a REAL result is produced; Eiffel Basic Types 35 2. The use of brackets to change the operator precedence; 3. The assignment instruction: first := first^3 +2 * second; The concept of assignment was introduced in the previous chapter. This example illustrates an important feature of assignment: a variable may be both the target of an assignment instruction, and also appear (more than once if required) on the right hand side of the assignment instruction. In such cases the target's value is altered; so that if first started with the value 2, and second with the value 3, after the instruction had executed, first would contain the value 14. The value of second would of course be unaltered. 3.3 BOOLEAN expressions Variables of type BOOLEAN may have one of two values, true and false. Boolean expressions may be formed from the relational operators defined in class COMPARABLE < > = and from the equality/inequality operators = /= both of which are members of the set of special symbols defined for Eiffel. Issues of equality are potentially complex in object-oriented languages, and this issue is discussed more fully in chapter 6. At this stage it is sufficient to regard Eiffel as providing a single set of relational operators for comparing numbers and characters: < > = = /= The following are examples of boolean expressions using each of the operators: 17 > 18 17 /= 18 17 = 17 ----- false true true true 17 < 18 17 = 18 17 >= 18 17 >= 17 ----- true false false true BOOLEAN expressions are used to form conditions for control instructions (chapter 4). They are also be used in assignment statements, and as arguments in procedure calls. Example 3.3 amends class SIMPLE by adding a new routine, do_comparisons, which is called from test, and also a new variable of type BOOLEAN, is_true. class SIMPLE; -- this class illustrates the use of boolean expressions creation test feature first,second:INTEGER; is_true: BOOLEAN; Eiffel Object-Oriented Programming36 do_comparisons is do end -- do comparisons do_simple_arithmetic is do end -- do simple arithmetic test is do .......... .......... -- do_simple_arithmetic - will not execute do_comparisons; end -- test end -- SIMPLE Example 3.3 Addition of a third routine to SIMPLE The reader should note that the routine, do_simple_arithmetic, may be left in class SIMPLE, and the call from test may either be removed, or commented out so that the compiler ignores it. Example 3.4 illustrate the use of boolean expressions in an assignment and as arguments to an output procedure. do_comparisons is do is_true := first > second; io.put_boolean(is_true); io.put_booean(first < second); end -- do comparisons Example 3.4 Boolean assignment and output Class SIMPLE may now be recompiled and executed. If at run time the values 17 and 18 are entered then the output should be false true We may add to our routine by inputting a boolean value, as shown in example 3.5. The reader is recommended to amend the routine do_comparisons as shown, and then to compile and execute it. do_comparisons is Eiffel Basic Types 37 do .... io.read_boolean; is_true := io.lastbool; io.put_boolean(is_true); end -- do comparisons Example 3.5 Boolean input from keyboard Finally, more complex expressions need to be considered. These may be constructed using the logical operators defined in class BOOLEAN. We may show the logic of the binary operators, and, or and xor in the truth tables in figure 1. a b a and b t t t t f f f t f f f f AND a b a OR b a b a XOR t t t t t f t f t t f t f t t f t t f f f f f f OR b Exclusive OR figure 1 The operand not is a unary operator which has the highest precedence of the boolean operators. If b is a boolean expression, then not b is true if and only if b is false. The precedence of the operators is as follows: high precedence not and and then Eiffel Object-Oriented Programming38 low precedence or implies xor or else The use of each can be illustrated as follows: EXPRESSION RESULT not ( 17 > 20) 17 < 20 and 17 > 16 17 > 20 and 17 > 16 17 > 20 or 17 > 16 17 < 20 or 17 > 16 17 < 20 xor 17 > 16 not (17 < 20 and 17 > 16) not (17 < 20 and 17 > 16) or 10 > 5 not (17 < 20) and 17 > 16 or 10 > 5 not (17 < 20 and 17 > 16 or 10 > 5) 17 < 20 xor 17 > 16 or 15 > 6 17 < 20 xor ( 17 > 16 or 15 > 6 ) 17 < 20 xor ( 17 > 16 xor 15 > 6 ) true true false true true false false true true false true false true The reader may now add the routine given in example 3.5 to class SIMPLE. do_complex_bool is do .... is_true:= not (first > second) and first >25 and second < 30; io.putbool(is_true); is_true := not (first > second or first >25 ) and second < 30; io.put_boolean(is_true); end -- do complex_bool Example 3.5 Use of logical operators The reader should be able to work out some values for 1 and 2 which will generate true for one or other expression. It is not possible, however, to make the above routine yield the output true true The reader is encouraged to execute it and try to prove the author wrong! The following section may be omitted on a first reading. Eiffel Basic Types 39 3.3 Semi-strict boolean operators There are additional boolean operators, known as semi-strict operators : and then or else implies The logic and precedence of and then and or else is the same as and and or respectively. The difference is that given the following expressions a and then b a or else b if a is false in the first case then b is not evaluated, since at that point it is known that the whole expression must be false. Similarly, if a is true in the second case then there is no need to evaluate b, since the whole expression must be true. These operators can be useful in conditions when the programmer may not wish to require the second operand to be evaluated because of the chance of a run-time error. For example a terminating condition on a search of a file might be end of file or key field matches search string In this case, when the first operand is true, at the end of file, there is no record to compare with the search string, and it is wise to avoid trying to evaluate the second operand. The use of the or else would allow us to ensure that the second expression was only evaluated when end of file was false. The operator implies has the lowest precedence of the boolean operators. The expression a implies b is the same as not a or else b. The expression is true, therefore, if a is false, otherwise the result is given by an evaluation of b. So, for example, the file search terminator previously discussed, could be rewritten as not end of file implies key field matches search string so that if the end of file is reached, the expression is true, otherwise the expression is true if key field matches the search string. The truth table for implies is given in figure 2. a a b implies b t t t t f f f t t f f t figure 2 Eiffel Object-Oriented Programming40 The implies operator may be further illustrated b

Valuable advice on finishing your ‘Blumberg T 186 Lease Form’ online

Are you fed up with the inconvenience of managing paperwork? Look no further than airSlate SignNow, the premier eSignature platform for individuals and organizations. Bid farewell to the tedious task of printing and scanning documents. With airSlate SignNow, you can effortlessly complete and sign documents online. Utilize the powerful features included in this user-friendly and cost-effective platform and transform your document management approach. Whether you need to sign forms or gather electronic signatures, airSlate SignNow takes care of everything smoothly, needing just a few clicks.

Adhere to this comprehensive guide:

  1. Log into your account or enroll for a complimentary trial of our service.
  2. Click +Create to upload a file from your device, cloud storage, or our forms repository.
  3. Open your ‘Blumberg T 186 Lease Form’ in the editor.
  4. Click Me (Fill Out Now) to set up the form on your end.
  5. Add and allocate fillable fields for others (if necessary).
  6. Continue with the Send Invite settings to solicit eSignatures from others.
  7. Download, print your copy, or convert it into a reusable template.

No need to worry if you wish to collaborate with others on your Blumberg T 186 Lease Form or submit it for notarization—our solution provides everything necessary to accomplish such tasks. Register with airSlate SignNow today and enhance your document management to new levels!

Here is a list of the most common customer questions. If you can’t find an answer to your question, please don’t hesitate to reach out to us.

Need help? Contact Support
Blumberg 186 lease agreement pdf
T 186 lease agreement pdf free download
T 186 lease agreement free
Blumberg lease form 186
Blumberg commercial lease pdf
Blumberg forms
New York residential lease agreement pdf
Blumberg rental Lease
Sign up and try Blumberg t 186 lease form
  • Close deals faster
  • Improve productivity
  • Delight customers
  • Increase revenue
  • Save time & money
  • Reduce payment cycles