OO Design with Multiple Inheritance

Similar documents
OO Design with Multiple Inheritance. Questions:

Chapter 5 Object-Oriented Programming

What are the characteristics of Object Oriented programming language?

PROGRAMMING LANGUAGE 2

Module 10 Inheritance, Virtual Functions, and Polymorphism

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

The major elements of the object-oriented model

What is Inheritance?

Lecture 5: Inheritance

ECE 122. Engineering Problem Solving with Java

Object Oriented Programming is a programming method that combines: Advantage of Object Oriented Programming

Graphical Interface and Application (I3305) Semester: 1 Academic Year: 2017/2018 Dr Antoun Yaacoub

Inheritance (Outsource: )

Lecture 36: Cloning. Last time: Today: 1. Object 2. Polymorphism and abstract methods 3. Upcasting / downcasting

Practice for Chapter 11

JAVA MOCK TEST JAVA MOCK TEST II

HAS-A Relationship. Association is a relationship where all objects have their own lifecycle and there is no owner.

Object-Oriented Programming Paradigm

VIRTUAL FUNCTIONS Chapter 10

Project. C++: Inheritance III. Plan. Project. Before we begin. The final exam. Advanced Topics. Project. This week in the home stretch

(11-1) OOP: Inheritance in C++ D & D Chapter 11. Instructor - Andrew S. O Fallon CptS 122 (October 29, 2018) Washington State University

Topic 7: Inheritance. Reading: JBD Sections CMPS 12A Winter 2009 UCSC

Chapter 14 Abstract Classes and Interfaces

C++ Inheritance and Encapsulation

Abstract Classes. Abstract Classes a and Interfaces. Class Shape Hierarchy. Problem AND Requirements. Abstract Classes.

HAS-A Relationship. Association is a relationship where all objects have their own lifecycle and there is no owner.

Lecture Contents CS313D: ADVANCED PROGRAMMING LANGUAGE. What is Inheritance?

CS111: PROGRAMMING LANGUAGE II

CSC9T4: Object Modelling, principles of OO design and implementation

CS111: PROGRAMMING LANGUAGE II

More about inheritance

Derived Classes in C++

CS313D: ADVANCED PROGRAMMING LANGUAGE

Making Inheritance Work: C++ Issues

Making Inheritance Work: C++ Issues

The Essence of Object Oriented Programming with Java and UML. Chapter 2. The Essence of Objects. What Is an Object-Oriented System?

CSCI-142 Exam 1 Review September 25, 2016 Presented by the RIT Computer Science Community

After a lecture on cosmology and the structure of the solar system, William James was accosted by a little old lady.

Inheritance, and Polymorphism.

Object Oriented Programming. Java-Lecture 11 Polymorphism

Inheritance -- Introduction

25. Generic Programming

Design issues for objectoriented. languages. Objects-only "pure" language vs mixed. Are subclasses subtypes of the superclass?

CS112 Lecture: Defining Classes. 1. To describe the process of defining an instantiable class

OBJECT ORİENTATİON ENCAPSULATİON

Inheritance. OOP components. Another Example. Is a Vs Has a. Virtual Destructor rule. Virtual Functions 4/13/2017

Java Fundamentals (II)

STUDENT LESSON A20 Inheritance, Polymorphism, and Abstract Classes

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

CS313D: ADVANCED PROGRAMMING LANGUAGE

Inheritance and Polymorphism

Programming using C# LECTURE 07. Inheritance IS-A and HAS-A Relationships Overloading and Overriding Polymorphism

Pieter van den Hombergh Thijs Dorssers Stefan Sobek. January 11, 2018

CREATED BY: Muhammad Bilal Arslan Ahmad Shaad. JAVA Chapter No 5. Instructor: Muhammad Naveed

Why use inheritance? The most important slide of the lecture. Programming in C++ Reasons for Inheritance (revision) Inheritance in C++

[ L5P1] Object-Oriented Programming: Advanced Concepts

CS11 Introduction to C++ Fall Lecture 7

Data Abstraction. Hwansoo Han

CSE 70 Final Exam Fall 2009

Java Programming Lecture 7

Data Structures and Other Objects Using C++

INHERITANCE. Spring 2019

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

More About Objects. Zheng-Liang Lu Java Programming 255 / 282

Polymorphism. Arizona State University 1

Name Return type Argument list. Then the new method is said to override the old one. So, what is the objective of subclass?

CMSC131. Inheritance. Object. When we talked about Object, I mentioned that all Java classes are "built" on top of that.

Introduction to C++ Introduction to C++ Dr Alex Martin 2013 Slide 1

Introduction to Design Patterns

Written by John Bell for CS 342, Spring 2018

Chapter 11 Object and Object- Relational Databases

4.1 Introduction Programming preliminaries Constructors Destructors An example... 3

Inheritance, Polymorphism and the Object Memory Model

Instance Members and Static Members

Inheritance. Lecture 11 COP 3252 Summer May 25, 2017

10/17/2011. Object Oriented Software Development. Types of interface. Interfaces example

ECE 462 Object-Oriented Programming using C++ and Java. Key Inputs in Java Games

Exheritance Class Generalisation Revived

First IS-A Relationship: Inheritance

Object Oriented Programming in Java. Jaanus Pöial, PhD Tallinn, Estonia

Announcement. Agenda 7/31/2008. Polymorphism, Dynamic Binding and Interface. The class will continue on Tuesday, 12 th August

INHERITANCE WITH JAVA INTERFACES

Sofa. Bed. SleeperSofa ss; weight. weight

Inheritance and object compatibility

Extending Classes (contd.) (Chapter 15) Questions:

Lesson 10A OOP Fundamentals. By John B. Owen All rights reserved 2011, revised 2014

Rules and syntax for inheritance. The boring stuff

Exercise: Singleton 1

CS112 Lecture: Inheritance and Polymorphism

Object Oriented Programming Part II of II. Steve Ryder Session 8352 JSR Systems (JSR)

Modern C++ for Computer Vision and Image Processing. Igor Bogoslavskyi

This week. Tools we will use in making our Data Structure classes: Generic Types Inheritance Abstract Classes and Interfaces

Pieter van den Hombergh Thijs Dorssers Stefan Sobek. February 10, 2017

Chapter 12. OOP: Creating Object-Oriented Programs The McGraw-Hill Companies, Inc. All rights reserved. McGraw-Hill

CHAPTER 3: FUNDAMENTAL OF SOFTWARE ENGINEERING FOR GAMES.

Chapter 12. OOP: Creating Object- Oriented Programs. McGraw-Hill. Copyright 2011 by The McGraw-Hill Companies, Inc. All Rights Reserved.

Copyright 2016 Ramez Elmasri and Shamkant B. Navathe

Object Oriented Programming: Based on slides from Skrien Chapter 2

Inheritance. Inheritance allows the following two changes in derived class: 1. add new members; 2. override existing (in base class) methods.

Transcription:

OO Design with Multiple Inheritance Multiple Inheritance in C++ C++ allows a class to inherit implementation code from multiple superclasses. inheritance (MI). This is referred to as multiple Some programmers like multiple inheritance because real-world entities (such as yourself) do inherit traits from multiple sources. Many programmers shun MI because it can introduce deeply hidden bugs into a large program and can make it more daunting to extend a class hierarchy. 1

Any design that uses multiple inheritance can be converted into one in which a class inherits implementation code from only one superclass. Java does not allow a class to inherit implementation code from multiple superclasses. However, Java does allow a class to inherit behaviors from multiple interfaces. 2

Some Simple Examples for MI Let s say we wish to use classes to represent the following roles in an educational system: Student Teacher TeachingAssistant Student Teacher ^ ^ -------- ------ TeachingAssistant 3

GenericVehicle PeopleHaulerTraits FreightHaulerTraits ^ ^ ^ ^ \ --------------/---------- \ / \ \ / \ \ / \ \ / \ PassengerVehicle FreightHauler PersonalTransporterTraits CommercialTransporterTraits ^ ^ ^ \ / / / / \ / / \ / / \ / ------ / \ / \ / \ / \ / \ / \ / Car Bus Truck FreightLiner 4

While the above two examples lend themselves straightforwardly to multiple inheritance, let s now consider an example where the decision to use multiple inheritance may be dictated by some basic tenet of object-oriented programming, such as keeping different data abstractions as loosely coupled as possible. 5

Let s say we want to model the various ways in which a set of mechanical widgets can be assembled in a factory. (We may want to do so to carry out a cost benefit analysis of the different methods for assembly.) 6

The assembly operations may be carried out robotically, manually, or semiautomatically using different systems. If parts are assembled from random initial positions in a work area, automatic and semiautomatic assembly would need some sort of a computer vision module for localizing the parts before they can be assembled. After the parts are localized, the computer would also have to calculate the motion trajectories to use for mating one part with another part. For that, it would need to know the initial and the final pose of each part. We will assume that the computer has available to it full 3D geometric models of the parts for such path planning calculations. 7

We obviously have the following three issues to deal with here and, for program organization, it is best to think of them separately: 1. Specifying the assembly operations at a purely abstract level. 2. The choice of the agent that would actually carry out the assembly again at an abstract level. The agent could be a robot, a human, or some semiautomatic system. 3. A geometry engine for computing the motion trajectories to be used for mating one part with another part when assembly is carried out robotically. Such motion trajectories may also be needed for some types of semiautomatic assembly. For manual assembly, the calculated motion trajectories may help us determine the level of dexterity expected of a human worker. 8

The first issue capturing at an abstract level the assembly operations needed could be addressed by defining an Assemble class as shown in the next slide. This class uses two ancillary classes: Part for representing the parts to be assembled, and Pose to represent the location and the orientation of each part in space. The class Part presumably has at least a data member that points to a geometric model of the part. Such models would be needed by a geometry engine to figure out the collision-free trajectories for assembling one part with another. 9

class Assemble { protected: Part* part1; // part1 to be assembled with part2 // part2 assumed fixtured Part* part2; Pose* part1_initial_pose; Pose* part1_final_pose; Pose* pose_part2; bool done; public: Assemble( Part1* p1, Part* p2, Pose* s1_init, Pose* s1_final, Pose* s2, done = false ); virtual void grasppart() {}; virtual void orientpart() {}; virtual void pickuppart() {}; virtual void insert() {}; virtual bool isassemblydone() { return done; } // the rest of the class virtual ~Assemble(); }; 10

The names of the member functions speak for themselves. As a data abstraction, the class Assemble stands on its own, independent of the physical mechanism used for assembly. The simplistic implementations provided for the functions are supposed to take care of the requirement that when a function is declared to be virtual, it must be defined at the same time. Obviously, their override definitions in the subclasses of Assemble would be more useful. 11

For addressing the second of the three issues outlined previously, we can now extend the Assemble class and provide more meaningful implementations for its various member functions depending on the specific assembly agent used. 12

class AssembleWithRobot : public Assemble { // stuff related to robot calibration // and the coordinate transformation from // the world frame into a robot end-effector // based coordinate frame public: AssembleWithRobot( Part1* part1, Part* part2, Pose* part1_init_pose, Pose* part1_final_pose, Pose* s2, done = false ); void grasppart(); void orientpart(); void pickuppart(); void insert(); // the rest of the class }; class AssembleSemiAutomatically : public Assemble { /*... */ }; class AssembleManually : public Assemble { /*... */ };... 13

The functions such as grasppart(), orientpart(), and so on, for the robotic and semiautomatic assembly would take into account the kinematic and dynamic constraints of the machines involved, but again at a purely abstract level. 14

Now we can write a function that, through polymorphism, could be used to perform assemblies: void assemble( Assemble* agent ) { agent->grasppart(); // grasp part1 agent->insert(); // insert part1 into part2 //... if ( agent->done() ) { // assembly finished, start next step } else { //... } //... } The important thing to note here is that the assemble() function is independent of the kind of Assemble object that we may actually be using. Polymorphism would guarantee us that, inside assemble(), the correct function is invoked for each Assemble. 15

This brings us to the issue of how to actually do geometry calculations for figuring out the motion trajectories needed for taking part1 from its initial pose, as given by the value of the data member part1 initial pose of the class Assemble, to its final pose, as given by the data member part1 final pose. The function insert() defined for Assemble would simply not work unless it has access to some kind of a geometry engine for path planning. The question now is: How do we incorporate the path planning facilities offered by a vendor-supplied geometry engine in the Assemble class hierarchy? 16

One option is to declare the GeometryEngine class as a base for the Assemble class: class Assemble : public GeometryEngine { protected: Part* part1; Part* part2; Pose* part1_initial_pose; Pose* part1_final_pose; Pose* pose_part2; bool done; public: Assemble( Part1* p1, Part* p2, Pose* s1_init, Pose* s1_final, Pose* s2, done = false ); virtual void grasppart(); virtual void orientpart(); virtual void pickuppart(); virtual void insert(); virtual bool isassemblydone() { return done; } // the rest of the class virtual ~Assemble(); }; 17

The path planning functions inherited from the GeometryEngine class would be overridden in each subclass of Assemble class to take into account the special constraints of the assembly agent corresponding to that class. Graphically, our class hierarchy for Assemble and its extensions would look like: GeometryEngine Assemble AssembleWithRobot AssembleSemiAutomatically AssembleManually AssembleWithSystem1 AssembleWithSystem2 18

While this design could be made to serve its intended function, it violates a basic tenet of good OO programming: Data abstractions that are conceptually separate and distinct should be kept as uncoupled as possible As originally conceived, the data abstraction represented by the class Assemble was complete unto itself and distinct from the path planning implementation code packaged in the GeometryEngine class. But, by making Assemble a subclass of GeometryEngine, we have destroyed the separate identity of Assemble. 19

Now we will show a different design in which we do not violate the separateness of the abstractions. In this new design, we will specify Assemble as a pure interface, meaning an abstract class with no implementation code: class Assemble { public: virtual void grasppart() = 0; virtual void orientpart() = 0; virtual void pickuppart() = 0; virtual void insert() = 0; virtual bool isassemblydone() = 0; // the rest of the class virtual ~Assemble() {}; }; Now that all the functions of Assemble are pure virtual, we do not have to provide them with the simplistic implementations that we had to in our previous design. Being an abstract class, our new Assemble class does not need a constructor. We have also included a virtual destructor that can be used for cleaning up the data to be defined in the derived classes. 20

Now the definition of AssembleWithRobot might look like: }; class AssembleWithRobot : public Assemble, protected GeometryEngine { Part* part1; Part* part2; Pose* part1_initial_pose; Pose* part1_final_pose; Pose* pose_part2; bool done; protected: // code for overriding any virtual functions of // GeometryEngine class public: AssembleWithRobot( Part1* p1, Part* p2, Pose* s1_init, Pose* s1_final, Pose* s2, done = false ); virtual void grasppart(); virtual void orientpart(); virtual void pickuppart(); virtual void insert(); virtual bool isassemblydone(); ~ AssembleWithRobot(); 21

Here we have multiple inheritance. In this particular implementation of MI, the nature of inheritance from the two bases of AssembleWithRobot is different. The public derivation from the base class Assemble will allow us to use polymorphism with respect to the virtual functions declared in that base class. On the other hand, the protected derivation from GeometryEngine will allow AssembleWithRobot and its subclasses to inherit the path planning implementation code in that base. With this construction, we are evidently making a design decision that we do not need polymorphism with respect to the path planning functions in GeometryEngine. It goes without saying that AssembleWithRobot class is required to provide implementations for all the abstract functions declared in the base Assemble. 22

The other derived classes in the Assemble hierarchy can now be defined as follows: class AssembleSemiAutomatically : public Assemble, protected GeometryEngine { /*... */ }; class AssembleManually : public Assemble, protected GeometryEngine { /*...*/ };... 23

GeometryEngine Assemble AssembleWithRobot AssembleSemiAutomatically AssembleManually AssembleWithSystem1 AssembleWithSystem2 protected derivation public derivation Graphically, the entire hierarchy can be shown as here. 24

The two approaches to the design we have presented are not the only ones available. Another possibility would be to use GeometryEngine* as a data member inside Assemble. That could be made to work, provided that GeometryEngine has no virtual member functions that would need to be overridden in Assemble and its subclasses. In any case, the MI-based design appears more natural and more logical to the situation at hand, and it meets a design criterion that it is best to keep distinct abstractions separate. Nonetheless, it is worthwhile to point out that the implementation code at the level of concrete classes such as AssembleWithRobot will remain substantially the same no matter which approach is used. 25

Issues that Arise with Repeated Inheritance The most complicating issues that arise with MI have to do with what is known as repeated inheritance. Repeated inheritance takes place when a derived class inherits the same members of some base class through two different paths in a class hierarchy. 26

Employee address name getname print setname Manager department level getlevel print setlevel SalesPerson department salestarget print setsalestarget setterritory SalesManager 27

The classes Manager and SalesPerson are both derived from the base class Employee. And the class SalesManager is derived from both Manager and SalesPerson. We have intentionally left unspecified the data members and the member functions in the final derived-class SalesManager, as the following discussion bears directly on their specification. 28

When a derived class can inherit members through multiple paths and when the different paths have an upstream class in common, the following issues become immediately relevant. 29

1. The Problem of Duplicate Construction of Common-Base Subobject: Recall from earlier discussion that when the constructor of a derived class is invoked, the derived-class object so constructed has built inside it a base-class subobject. Base class slice of the derived-class object Derived-class object 30

That implies that, unless precautions are taken, when a constructor for SalesManager is invoked, we would end up with two different versions of the Employee slice in the constructed object. Employee Employee Manager SalesPerson SalesManager How do we prevent the formation of duplicate common-base subobjects in a derived-class object? 31

2. The Name-Conflict Problem for Member Functions: Suppose two member functions of the same signature but different implementations are inherited by the SalesManager class from the two different inheritance paths shown. If these member functions are not overridden in the SalesManager class, we can end up with an ill-formed program. This could, for example, be the case with the print() member function that is listed originally as a member of the class Employee. Let s say this function is modified by each class between Employee and SalesManager. If for some reason, this modified function is not overridden in SalesManager but yet invoked on an object of type SalesManager, you would have a compile-time ambiguity. 32

3. The Name-Conflict Problem for Data Members: The class SalesManager inherits two different data members with the same name department one each from the two superclasses Manager and SalesPerson. These two data members, although possessing the same name, possess different meanings for the derived class SalesManager because a SalesManager could conceivably have two different department attributes associated with him or her. Such an individual could belong to a particular department of the corporation and, at the same time, be in charge of a particular unit of the sales organization which could also be referred to as a department. So how does one make sure that despite the same name department each data member gets the correct value when we construct an object of type SalesManager? 33