Ranga Rodrigo Based on Marc Priestley's Lectures

Slides:



Advertisements
Similar presentations
OO Programming in Java Objectives for today: Overriding the toString() method Polymorphism & Dynamic Binding Interfaces Packages and Class Path.
Advertisements

Chapter 1 Object-Oriented Concepts. A class consists of variables called fields together with functions called methods that act on those fields.
Inheritance 2 Ranga Rodrigo Based on Mark Priestley's Lectures.
Inheritance Inheritance Reserved word protected Reserved word super
ACM/JETT Workshop - August 4-5, :Inheritance and Interfaces.
Inheritance and object compatibility Object type compatibility An instance of a subclass can be used instead of an instance of the superclass, but not.
ITEC200 – Week03 Inheritance and Class Hierarchies.
1 Lecture 3 Inheritance. 2 A class that is inherited is called superclass The class that inherits is called subclass A subclass is a specialized version.
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Principles of Object-Oriented Software Development The language Eiffel.
Chapter 10 Classes Continued
8.1 Classes & Inheritance Inheritance Objects are created to model ‘things’ Sometimes, ‘things’ may be different, but still have many attributes.
Ranga Rodrigo. Class is central to object oriented programming.
220 FINAL TEST REVIEW SESSION Omar Abdelwahab. INHERITANCE AND POLYMORPHISM Suppose you have a class FunClass with public methods show, tell, and smile.
Introduction to Object Oriented Programming. Object Oriented Programming Technique used to develop programs revolving around the real world entities In.
1 Java Inheritance. 2 Inheritance On the surface, inheritance is a code re-use issue. –we can extend code that is already written in a manageable manner.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
More About Classes Ranga Rodrigo. Information hiding. Copying objects.
Inheritance in the Java programming language J. W. Rider.
RIT Computer Science Dept. Goals l Inheritance l Modifiers: private, public, protected l Polymorphism.
Genericity Ranga Rodrigo Based on Mark Priestley's Lectures.
Chapter 3 Inheritance and Polymorphism Goals: 1.Superclasses and subclasses 2.Inheritance Hierarchy 3.Polymorphism 4.Type Compatibility 5.Abstract Classes.
8. Inheritance “Is-a” Relationship. Topics Creating Subclasses Overriding Methods Class Hierarchies Abstract Class Inheritance and GUIs The Timer Class.
1 COSC2007 Data Structures II Chapter 9 Class Relationships.
Application development with Java Lecture 21. Inheritance Subclasses Overriding Object class.
1 Inheritance Reserved word protected Reserved word super Overriding methods Class Hierarchies Reading for this lecture: L&L 9.1 – 9.4.
Method Overriding Remember inheritance: when a child class inherits methods, variables, etc from a parent class. Example: public class Dictionary extends.
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Inheritance and Class Hierarchies Chapter 3. Chapter Objectives  To understand inheritance and how it facilitates code reuse  To understand how Java.
Inheritance and Polymorphism
More About Classes Ranga Rodrigo. Quiz: Question 1 Write the following C++ code in Eiffel. void covert { int i ; float f(1.41) ; i = (int) f ; }
Terms and Rules II Professor Evan Korth New York University (All rights reserved)
Liang, Introduction to Java Programming, Ninth Edition, (c) 2013 Pearson Education, Inc. All rights reserved. 1 1 Chapter 15 Abstract Classes and Interfaces.
Notices Assn 2 is due tomorrow, 7pm. Moodle quiz next week – written in the lab as before. Everything up to and including today’s lecture: Big Topics are.
Lecture 6:Interfaces and Abstract Classes Michael Hsu CSULA.
Java Programming: Guided Learning with Early Objects Chapter 9 Inheritance and Polymorphism.
Class Inheritance Part II: Overriding and Polymorphism Corresponds with Chapter 10.
Lecture 5:Interfaces and Abstract Classes
Inheritance Modern object-oriented (OO) programming languages provide 3 capabilities: encapsulation inheritance polymorphism which can improve the design,
Modern Programming Tools And Techniques-I
Inheritance Chapter 7 Inheritance Basics Programming with Inheritance
Inheritance and Polymorphism
Agenda Warmup AP Exam Review: Litvin A2
Week 4 Object-Oriented Programming (1): Inheritance
Programming Language Concepts (CIS 635)
Road Map Inheritance Class hierarchy Overriding methods Constructors
Inheritance Chapter 7 Inheritance Basics Programming with Inheritance
Chapter 13 Abstract Classes and Interfaces
Object Oriented Programming (OOP) LAB # 8
Inheritance Basics Programming with Inheritance
CISC124 Assignment 4 on Inheritance due next Monday, the 12th at 7pm.
OOP Paradigms There are four main aspects of Object-Orientated Programming Inheritance Polymorphism Abstraction Encapsulation We’ve seen Encapsulation.
Java Programming Language
MSIS 670 Object-Oriented Software Engineering
Advanced Java Topics Chapter 9
Chapter 12 Abstract Classes and Interfaces
Computer Programming with JAVA
Java – Inheritance.
Java Inheritance.
Einführung in die Programmierung Introduction to Programming Prof. Dr
Inheritance Chapter 7 Inheritance Basics Programming with Inheritance
Einführung in die Programmierung Introduction to Programming Prof. Dr
Chapter 9 Carrano Chapter 10 Small Java
Chapter 14 Abstract Classes and Interfaces
Chapter 9 Inheritance.
Review of Previous Lesson
Einführung in die Programmierung Introduction to Programming Prof. Dr
Review of Previous Lesson
CS 112 Programming 2 Lecture 02 Abstract Classes & Interfaces (2)
Presentation transcript:

Ranga Rodrigo Based on Marc Priestley's Lectures Inheritance Ranga Rodrigo Based on Marc Priestley's Lectures

Quiz: Question 1 The following set of slides show two classes, point and line. Write down the output that corresponds to the main file shown.

class LINE create make feature p1_ : POINT p2_ : POINT make ( p1 : POINT; p2 : POINT ) is do p1_ := p1 p2_ := p2 ensure p1_ = p1 p2_ = p2 end display is io.put_string ("line from ") p1_.display io.put_string (" to ") p2_.display is_equal( l : LINE ) : BOOLEAN is Result := equal(p1_, l.p1_) and equal(p2_, l.p2_) class POINT create make feature x_ : INTEGER y_ : INTEGER make ( x : INTEGER; y : INTEGER) is do x_ := x y_ := y ensure x_ = x y_ = y end display is io.put_string ("point (") io.put_integer (x_) io.put_string (", ") io.put_integer (y_) io.put_string (")")

class MAIN create make feature -- Initialization origin, p1, p2, p3, p4: POINT line1, line2 : LINE make is do create origin.make (0, 0) create p1.make(1,2) create p2.make(1,2) create p3.make (5,5) create line1.make (origin, p1) create line2.make (origin, p2) p3.copy(origin) p4 := clone(origin) io.put_string ("1. ") io.put_boolean(equal(p1, p2)) io.new_line io.put_string ("2. ") io.put_boolean(p1.is_equal(p2)) io.put_string ("3. ") io.put_boolean(equal(line1, line2)) io.new_line io.put_string ("4. ") io.put_boolean(line1.is_equal(line2)) io.put_string ("5. ") io.put_boolean(deep_equal(line1, line2)) io.put_string ("6. ") io.put_boolean(line1.is_equal (line2)) io.put_string ("7. ") p3.display io.put_string ("8. ") p4.display end

Quiz: Question 2 Assuming that a, b, c, d, e, f, g, and h are declared as instances of type, e.g., LINE, explain the operation done by each of the flowing snippets. Indicate the depth (shallow, or deep) and whether the objects need to have been already created. b.copy(a) d.deep_copy(c) f := clone(e) h := deep_clone(g)

Quiz: Question 3 Consider the following code. Why would it not compile? How would you make the played attribute only accessible/mutable by a child class of RESULTS called SOCCER_RESULTS and its descendents? How would you make the played attribute public accessible/mutable?

class RESULTS feature {} points : ARRAY[INTEGER] feature played : INTEGER total : INTEGER ... end compare( r : RESULTS ) is do if r.points[0] > points[0] then io .put_string("They did better.")

Solution: Question 1 1. True 2. True 3. False 4. False 5. True 6. True 7. point (0, 0) 8. point (0, 0) 1.5 marks each (12)

Solution: Question 2 One mark Each (5) Object Depth Creation Comments a,c,e,g Not applicable Should have already been created. These are the sources for copying or cloning. b.copy(a) b will be a shallow copy of a b should have already been created. d.deep_copy(c) Deep d should have already been created. f := clone(e) Shallow f will be created. h := deep_clone(g) One mark Each (5)

Quiz: Question 3 Consider the following code. 1. Why would it not compile? No class has access to the feature points. So the instances of RESULTS itself do not have access to it. Therefore the line r.points[0] > points[0] will not compile. 2. How would you make the played attribute only accessible/mutable by a child class of RESULTS called SOCCER_RESULTS and its descendents? feature {SOCCER_RESULTS} Played : INTEGER 3 marks 3 marks

Quiz: Question 3 3. How would you make the played attribute public accessible/mutable? feature {ANY} Played : INTEGER 2 marks

Inheritance and Redefinition Suppose we wanted to extend the functionality of the COUNTER class discussed in Lecture 3, so that it could support counter which emitted a sound whenever the count was incremented. One way to do this would be to define the new class as a subclass of COUNTER, and to override, or redefine, the increment routine to include the new functionality.

COUNTER class from Lecture 03 Page 1 class COUNTER create make feature value: INTEGER_32 max: INTEGER_32 make (m: INTEGER_32) require valid_maximum: m > 0 do max := m ensure value_initialized: value = 0 max_initialized: max = m end increment not_at_maximum: not at_max value := value + 1 value_incremented: value = old value + 1 maximum_constant: max = old max

COUNTER class from Lecture 03 Page 2 at_max: BOOLEAN do if value < max then Result := False else Result := True end ensure Result = (value = max) display io.put_integer (value) io.new_line invariant value_in_range: 0 <= value and value <= max

AUDIBLE_COUNTER class inherits from COUNTER class class redefine increment end create make feature increment is do value := value + 1 io.put_string("Beep%N")

Inheritance in Eiffel Child classes inherit all features of their parents, so for example, the new increment routine can refer to and alter the value feature. If a routine is to be redefined in the subclass, it must be declared in a redefine clause following the name of the class it was originally declared in.

Inheritance in Eiffel Creation routines are inherited, as are all routines. However, the subclass must include a create clause to declare what its own creation routines are. New features can be added in child classes. Zero-argument functions can be redefined as attributes, but not vice versa. Features can be frozen, and cannot then be redefined.

Calling Routines from Superclass This example repeats the code contained in the increment routine that is being redefined. In general, this is a bad idea, and Eiffel provides the following way to call the routine that is being overridden: The Precursor statement calls the increment routine from the superclass COUNTER. increment is do Precursor io.put_string("Beep%N") end

Polymorphism As with other object-oriented languages, references to subclasses can be stored in variables which have the type of the superclass: class MAIN create make feature c : COUNTER make is do create {AUDIBLE_COUNTER} c.make(9999) c.increment io.put_integer(c.value) end

Polymorphism class MAIN create make feature c : COUNTER make is do create {AUDIBLE_COUNTER} c.make(9999) c.increment io.put_integer(c.value) end Creating an instance of the AUDIBLE_COUNTER Increment routine of the AUDIBLE_COUNTER called

Polymorphism Example The first line of make shows how to create an instance of the AUDIBLE_COUNTER class and store a reference to it in a variable whose compile-time type is COUNTER. In the second line, dynamic binding ensures that the increment routine from AUDIBLE_COUNTER is called. Even though c is declared to be of type COUNTER, this call will result in a beep being emitted. In the final line, the inherited value attribute of the counter is accessed as normal.

Renaming Features A feature cannot be redefined if its signature changes, e.g., if it has to take another parameter. This often happens with creation routines, where additional data is required to initialize subclass instances. However, Eiffel does not allow overloading, so attempting to have two routines with the same name will lead to a compilation error. A common solution is to rename the inherited routine:

Renaming: Page 1 class AUDIBLE_COUNTER inherit COUNTER rename make as make_counter redefine increment end create make feature beep_tone : STRING make( m : INTEGER ; b : STRING ) is do make_counter( m ) beep_tone := b increment is ... Renaming: Page 1 Renaming the inherited routine Notice that Precursor cannot be used in the make routine because we have renamed the inherited make routine as make_counter instead of redefining it.

Renaming: Page 2 increment is do Precursor io.put_string( beep_tone + "%N" ) end Renaming: Page 2

Inheritance and Specialization The conventional use of inheritance, as exemplified in UML and Java and illustrated above with the counter classes, is where subclasses define specialized cases of superclasses, and can redefine or add to the inherited functionality. The important thing here is substitutability: references to subclass instances can be stored in superclass variables, and a program should not be able to tell the difference. This is implemented using polymorphism and dynamic binding, as shown above.

Effect of Undefining and Renaming In Eiffel, unlike Java, the interface of a subclass need not contain everything defined in the interface of the superclass. Renaming a feature leads to this effect, and Eiffel allows other possibilities such as undefining features and changing the access level of features. This can make it look as if polymorphism will not work, as in the following example:

Notice that the child class PARENT feature socialize is do io.put_string("I say old chap!") end CHILD inherit rename socialize as party redefine party party is io.put_string("Hey, dude!") PARENT class CHILD class Notice that the child class renames the method from the parent class before redefining it.

Effect of Undefining and Renaming Given these classes, it looks like the code ought not to work: p is referencing an object of class CHILD, but there is no feature called socialize in the CHILD class, because it's been renamed. However, it works fine. We will see why in the next slide. p : PARENT create { CHILD } p p.socialize

Name-Based Look Up Why? The answer is that Eiffel uses a different method for looking up routines at run-time than C++ or Java. In those languages, a call like p.socialize would be interpreted as follows: Look at the run-time type of the object p points to (i.e., CHILD) Find a function called socialize in that class, and report a problem because there isn't one. In other words, it is a name-based look-up method. In Eiffel, this will not work, because of renaming.

Feature-Based Look Up Eiffel uses a different rule: Look for the feature named in the static call, i.e., socialize in class PARENT. Find the corresponding feature in the relevant run-time class, CHILD. socialize has been renamed as party, and then party has been redefined, so the required feature is the new method in the CHILD class. So, Eiffel uses a feature-based look-up method. party in class CHILD is the same feature as do_socialize in class PARENT, even though it's got a different name.

Look Up Methods: Summary Name-Based Feature-Based C++ Java Eiffel

Inheritance for Code Resuse Re-use of code is nowadays mostly accomplished using composition. For example, the RESULTS class defined earlier reused the code in the ARRAY class to store data: it did this by defining an attribute which stored a reference to the array. Code reuse can also be accomplished using inheritance, however. This style of programming has gone out of fashion, but it plays an important role in the design of the Eiffel libraries. Here is the RESULTS class implemented using inheritance:

Renaming the constructor class RESULTS inherit ARRAY[INTEGER] rename make as make_array end create make feature played : INTEGER total : INTEGER make( games : INTEGER ) is do make_array(1, games) add_result( pts : INTEGER ) is played := played + 1 put( pts, played ) total := total + pts Class inherits from ARRAY[INTEGER] Renaming the constructor CHILD class features

Implications of Inheritance This class inherits from ARRAY[INTEGER] rather than storing a reference to an array of that type. This means that all the features of the array class are features of the RESULTS. The array constructor must be renamed and called in the constructor for the RESULTS. Instead of points.put(pts, played) the code can now simply be written as put(pts, played) as the put method is inherited by the RESULTS.

Disadvantage of Inheriting from ARRAY One disadvantage of this is that all the features of the array class are inherited by RESULTS with the same access level as they had in the array class. This means that they are available to clients, who could therefore access the array of points directly. To counter this problem, we can change the access level of the features that are inherited from the array class:

class RESULTS inherit ARRAY[INTEGER] rename make as make_array export { NONE } all end Private inheritance

Private Inheritance This is essentially the same as private inheritance in C++, though Eiffel allows more control over what access levels are given to the inherited features. Different features can be given different access levels, and the access level can be specified in the same way as in a feature clause.

Facility Inheritance How do languages define globally accessible functions like sqrt? In C++ or Java, these are typically defined in classes which are made up of static methods only. Such classes are effectively modules, in the sense of Modula-2: there is no intention to create instances of them. In Eiffel, there are no static features of classes. So, the required functions must be defined in a normal class. They can then be used by inheriting the class that defines them, a technique known as facility inheritance:

class POINT inherit ARITHMETIC feature ... distance : REAL is do Result := sqrt(x*x + y*y) end

Facility Inheritance Here sqrt is a feature of POINT, because of inheritance. This technique seems to violate the intuition that inheritance is to do with classification of objects. It is hard to give a definition of the ARITHMETIC class: Meyer comes up with "an object that needs access to arithmetic functions", which seems a bit arbitrary, and it seems odd to say that sqrt is a feature of a point.

Inheritance from Interfaces Java allows classes to implement a number of interfaces as well as extending a class. C++ and Eiffel have no specific interface construct, but can use abstract or deferred classes for much the same purpose.

Inheritance from Interfaces For example, the Eiffel library includes a deferred class called COMPARABLE which defines the comparison operations >, <, >= and <=. To make these operators available, COMPARABLE should be inherited and the < operator redefined. For example, suppose we wanted to be able to compare teams in terms of who had the most points:

class RESULTS inherit COMPARABLE redefine infix "<" end create Make feature { } -- protected points : ARRAY[INTEGER] feature { ANY } -- public played : INTEGER total : INTEGER

make( games : INTEGER ) is do create points.make(1, games) end add_result( pts : INTEGER ) is played := played + 1 points.put( pts, played ) total := total + pts infix "<" (other: like Current): BOOLEAN is Result := total < other.total

Deferred Class Approach The deferred class approach does seem to have the advantage over Java's interfaces that it is possible to define a set of operations, such as >, <= and >+ in this case, in terms of a single deferred operation. If COMPARABLE was an interface, it would be necessary for the RESULTS class to redefine all these operations. However, making this useful requires that the language supports multiple inheritance.