Introduction to Eiffel
Object-oriented programming draws on just a few main ideas. I will talk about three of the important ones and illustrate their realization in the Eiffel language.
The first important idea is encapsulation: the packaging of data with means to manipulate it. Such a package, written in a programming language is a class, but an instance of a class in execution (or in storage) is an object.
In Eiffel, everything exists within a class. There are no external variables or routines. A class has features. Features in turn are either attributes or routines.
Attributes store values, including references to objects. They may be constant or variable.
Routines do things. Routines are either procedures or functions. Functions return results and are not supposed to change system state. Procedures change system state but return nothing.
All features, even constant or variable attributes, are said to be “called”. This is perhaps less strange than it might seem, for in Eiffel, a call to a function with no arguments is written the same as a call to an attribute. If in some class you write:
that := the.other
the.other may be either a function or an attribute, in this context it makes no difference.
So, you encapsulate data and the routines that manipulate it in a class. Assertions, mentioned previously, are also parts of a class and serve to express class preconditions, constraints and invariants.
The second important idea is inheritance.
Once you have a class, which describes what you know about the how and why of some sort of object, it may further benefit you to derive a new class from it, with additions and variations, without touching the program code in the original class. Inheritance is a mechanism that allows this.
For example, you might derive BEE from INSECT. Many features of BEE would inherit directly from INSECT, some features would be modified, and BEE would provide a few new features of its own.
A rule of thumb, called the “is-a” rule, furnishes one way to determine whether A might usefully inherit from B. Examine the sentence “A is a B”. Does it make sense? It should if A is a reasonable candidate to inherit from B. For example, “BEE is an INSECT” passes this test, so BEE might inherit from INSECT. Then, INSECT will be ancestor of BEE, and BEE will be a descendent INSECT.
The “has-a” rule furnishes a contrast. If “A has a B” makes more sense than “A is a B”, it may be prudent to let A reference or have a feature of type B, rather than inheriting from B. “BEE has a STINGER” makes more sense than “BEE is a STINGER” or for that matter “STINGER is a BEE”. Therefore, class BEE should have a feature of type STINGER. That makes BEE a client of STINGER, and STINGER a supplier to BEE.
The client-supplier relationship offers a client less detailed control than a descendent. A client may use or not use a feature of a supplier, but it cannot redefine such a feature. Many of a supplier's features may be hidden from a client, while they will be visible to a descendent. The positive side of this is that the client will be relatively unaffected by details of a supplier's implementation and less likely to be impacted by changes in a supplier.
Both client and inheritance relationships can facilitate software reuse. The traditional function call is more akin to the client relationship, and many attempts at reuse in the past, prior to object-oriented approaches, have made use of the function call. However, we still find ourselves writing and rewriting familiar pieces of functional code too complex to make good candidates for library routines.
The implementation details of inheritance may seriously affect its suitability as a mechanism for reuse. In the ideal implementation, problems arising in descendent classes could always be resolved there. Unfortunately, with many languages, problems arising in descendent classes require changes to ancestors.
This becomes more true with multiple inheritance, a technique by which a class may enjoy, or perhaps not enjoy, multiple ancestors. This technique is a powerful one, but it is unavailable in many object-oriented languages and discouraged in most of the rest. Among languages that have reached commercial viability, Eiffel offers a superior implementation of multiple inheritance.
In its broad sense, this indicates a situation where a simple request may elicit different but not entirely inconsistent responses, depending on the target of the request. These responses may be arrived at by entirely different means.
For example, you might have classes that look in part like this:
class INSECT -- Description of a standard -- insect. ... feature flee is do -- How a standard -- insect flees. ... end; -- flee end class BEE inherit INSECT redefine flee end; ... feature flee is do -- How a bee flees. ... end; --flee end class COCKROACH inherit INSECT redefine flee end; ... feature flee is do -- How a cockroach flees. ... end; -- flee end class WATERBUG inherit INSECT redefine flee end; ... feature flee is -- How a water bug flees. ... end; -- flee end
Then, you might have examples of BEE, COCKROACH, and WATERBUG bound to references of INSECT:
-- Define references to an -- INSECT and to a BEE. insect:INSECT; bob:BEE; -- Bind some particular -- insect to the reference insect := bugs.get -- Now you have a BEE, a -- COCKROACH or a WATERBUG. -- Make it flee after its own -- fashion, be it that of BEE, -- COCKROACH, or WATERBUG. -- This is a polymorphic call, -- as the code executed will -- depend on the type of the -- object bound to insect. insect.flee; -- You can't make a WATERBUG -- collect pollen. -- For this you need a BEE, and -- a trial assignment is -- available to assign objects -- that might conform to the -- type of a reference. bob ?= insect; -- Then maybe you can make bob -- the bee collect pollen. -- If he isn't a BEE or a -- conforming type, bob is Void. if bob /= Void then bob.collect_pollen end;
Another sort of polymorphism, sometimes called parametric polymorphism, is supported in Eiffel as genericity.
The final sort of polymorphism I'll mention is found as function overloading in other languages. Here, a function may be defined multiple times, with different types and numbers of arguments. When the function is called, the actual function invoked depends on the argument list.
Function overloading is not implemented in Eiffel. Workarounds are present, and arithmetic operations are handled as special cases, but the general case of function overloading is felt by the designers of Eiffel to be too full of potential ambiguities, type-checking failures, complications, and interactions to be worthwhile just now. A lively thread on this topic is seen from time to time on the newsgroup comp.lang.eiffel.
|Speed Up Your Web Site with Varnish||Jun 19, 2013|
|Non-Linux FOSS: libnotify, OS X Style||Jun 18, 2013|
|Containers—Not Virtual Machines—Are the Future Cloud||Jun 17, 2013|
|Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer||Jun 12, 2013|
|Weechat, Irssi's Little Brother||Jun 11, 2013|
|One Tail Just Isn't Enough||Jun 07, 2013|
- Speed Up Your Web Site with Varnish
- Containers—Not Virtual Machines—Are the Future Cloud
- Linux Systems Administrator
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Non-Linux FOSS: libnotify, OS X Style
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- RSS Feeds
- Reply to comment | Linux Journal
25 min 51 sec ago
- Reply to comment | Linux Journal
4 hours 25 min ago
- Yeah, user namespaces are
5 hours 41 min ago
- Cari Uang
9 hours 13 min ago
- user namespaces
12 hours 6 min ago
12 hours 32 min ago
- One advantage with VMs
15 hours 1 min ago
- about info
15 hours 34 min ago
15 hours 35 min ago
15 hours 36 min ago
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?