Classes Ranga Rodrigo Class is central to object
Classes Ranga Rodrigo
Class is central to object oriented programming.
Classes are abstractions of real-world entities. Classes support data abstraction, by providing an operational interface to some protected data. They make software components easily reusable.
Classes Versus Objects Class • Blueprint Objects • Buildings
Many Objects of a Class Object 1 … Object n
Attributes are synonymously known as In Eiffel Member variables Attributes are features.
Methods are synonymously known as Member functions (functions and procedures) In Eiffel Methods are features.
Features Attributes Methods Functions (return things) Procedures (don not return things)
Counter Example �Counters store (and make available through a display) a number. �Every time the user clicks a button, or similar interface widget, the number stored is increased. �There is a reset button, to set the count back to 0. �There will usually be a maximum permissible count value.
Attributes in Our Counter �The role of a counter is to store a numeric value. �We can define an attribute which stores the current value of the counter.
COUNTER Class in Counter. e File class COUNTER feature value : INTEGER end
value Attribute �This attribute is visible to all classes that use the counter class (client code). �In Java or C++ it is normal to make attributes private �to prevent client code changing the value of the attribute , and �to protect client code from modification if the representation of the attribute changes. �In Eiffel, these benefits are supported in different ways �Client classes have read-only access to attributes. �Uniform access.
Read-Only Access to Attributes
class MAIN create make feature c : COUNTER make is do create c io. put_integer(c. value) --Read access ok c. value : = 42 --Compilation error here end
Uniform Access �If the type of an attribute is changed, the original attribute can be replaced by a function. �Eiffel's syntax ensures that client code will not be affected by such a change. �This is known as the Uniform Access Principle. �There is no way for client code to tell whether an “attribute” of a class is implemented as an attribute or as a function.
class COUNTER feature value_rep : REAL value : INTEGER is do Result : = value_rep. floor end
Class Invariants �The collection of attributes in a class is sometimes said to define the state of instances of the class. �A class invariant is a property which specifies which are the legitimate values of a class's attributes.
class COUNTER feature value : INTEGER invariant value_in_range: 0 <= value and then value < 1000 end
Class Invariants �An invariant section can be written at the end of a class text, and can contain any number of Boolean conditions. �Each condition can be given a label to help identify it. �There are two main benefits: �Documentation. �Debugging: an Eiffel project can be configured to check invariants at run-time.
Constructors �Constructors, or creation routines as they are called in Eiffel, initialize attribute values when a new object is created.
class COUNTER creation make feature value : INTEGER maximum : INTEGER make( max : INTEGER ) is do maximum : = max end invariant value_in_range: 0 <= value and value <= maximum end
Calling the Constructor �Because make is defined here to be a creation routine, whenever an instance of the counter class is created, the desired constructor must be called: �create c. make(9999)
Pre- and Post-Conditions Preconditions • We should check that the parameters, if any, are valid. The conditions that check these are called the routine's preconditions and are written in Eiffel in a require clause before the routine's body. Postconditions • We should check that the routine has done what it should. The conditions that check this are called the routine's postconditions and are written in Eiffel in an ensure clause after the routine's body.
make( max : INTEGER ) is require valid_maximum: max > 0 do maximum : = max ensure value_initialized: value = 0 max_initialized: maximum = max end
Old �Sometimes, a postcondition should compare the value before the routine ran with its value after. The original value can be accessed using the keyword old. increment is require not_at_maximum: value < maximum do value : = value + 1 ensure value_incremented: value = old value + 1 maximum_constant: maximum = old maximum end
Precondition �The precondition states that the routine can only be successfully called if the maximum value has not been reached. �Notice that the body of the routine does not check that the value is less than the maximum. �As we will see later, this is part of the design by contract (DBC) philosophy.
Precondition �We should now add to the class a function which allows clients to check whether or not the counter is at the maximum value. �Without this, they have no way of checking that the precondition is true before calling increment. �A function is a routine that returns a value. Each function has a predefined local variable called Result: the value in this variable when control returns to the caller is the return value of the function. �The return value can be specified by using Result in the function's postcondition.
at_max : BOOLEAN is do if value < maximum then Result : = false else Result : = true end ensure Result = (value = maximum) end
Incrementing �It would be better to use this function to define the precondition of increment: this means that the details of the check are written in one place only, and hence that the code is more maintainable. increment is require not_at_maximum: not at_max do . . . end
Design by Contract (DBC) �One important aspect of design by contract is the specification of classes using �invariants, �preconditions and �post-conditions.
Preconditions Postconditions Invariants DBC
Eiffel. Studio Support for DBC �Eiffel. Studio allows controls over which aspects of a class's specification are checked at runtime. �Typically, you might check everything when developing a program, and only preconditions when it was delivered to a client. �Contract view shows the specification but omits the implementation of routines. �This gives enough information for a client to use the class.
DBC in Java �Java does not support DBC in the integrated way that Eiffel does. �Assertion facility which can be used to provide some of the same functionality. �Program must be run with enableassertions or es flag. �java -ea Main �Then an exception will be raised and the execution terminated if any assertion is false
public class Counter { private int value ; private int maximum ; public Counter(int max) { assert max > 0 : "Precondition failure: Counter" ; value = 0 ; maximum = max ; call_invariant() ; assert value == 0 && maximum == max : "Postcondition failure: Counter" ; } CONTD.
CONTD. public int get. Value() { return value ; } public void call_invariant() { assert 0 <= value && value <= maximum : "Counter invariant failure" ; } }
Eiffel and Java DBC: Differences �Eiffel syntax clearly separates the contract of the class from its implementation. �Java provides no way of calling the class invariant automatically at the appropriate times. �Java does not provide an easy way of accessing the old values of attributes.
- Slides: 37