Using Inheritance to Share Implementations CS 5010 Program Design Paradigms "Bootcamp" Lesson 12.1 © Mitchell Wand, 2012-2014 This work is licensed under.

Slides:



Advertisements
Similar presentations
Real State vs. Simulated State CS 5010 Program Design Paradigms "Bootcamp" Lesson 11.3 © Mitchell Wand, This work is licensed under a Creative.
Advertisements

Basics of Inheritance CS 5010 Program Design Paradigms "Bootcamp" Lesson 12.1 © Mitchell Wand, This work is licensed under a Creative Commons.
Testing Simple Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.6 © Mitchell Wand, This work is licensed under a Creative Commons.
Patterns of Interaction 2: Publish-Subscribe CS 5010 Program Design Paradigms "Bootcamp" Lesson 11.6 © Mitchell Wand, This work is licensed under.
The Function Design Recipe CS 5010 Program Design Paradigms “Bootcamp” Lesson 1.1 TexPoint fonts used in EMF. Read the TexPoint manual before you delete.
Interfaces CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.2 © Mitchell Wand, This work is licensed under a Creative Commons Attribution-NonCommercial.
Linear Search CS 5010 Program Design Paradigms “Bootcamp” Lesson 9.1 TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.:
Classes, Objects, and Methods CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.1 © Mitchell Wand, This work is licensed under a Creative.
Language Issues for Inheritance CS 5010 Program Design Paradigms "Bootcamp" Lesson 12.3 © Mitchell Wand, This work is licensed under a Creative.
Lists CS 5010 Program Design Paradigms “Bootcamp” Lesson 4.1 TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AAA 1 ©
Function Composition CS 5010 Program Design Paradigms “Bootcamp” Lesson © Mitchell Wand, This work is licensed under a Creative Commons.
Structural Decomposition CS 5010 Program Design Paradigms “Bootcamp” Lesson 2.1 © Mitchell Wand, This work is licensed under a Creative Commons.
Stateful Objects and Stable Identities CS 5010 Program Design Paradigms "Bootcamp" Lesson 11.2 © Mitchell Wand, This work is licensed under a.
Classes, Objects, and Interfaces CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.3 © Mitchell Wand, This work is licensed under a Creative.
Mutually-Recursive Data Definitions CS 5010 Program Design Paradigms “Bootcamp” Lesson 6.4 © Mitchell Wand, This work is licensed under a Creative.
Foldr CS 5010 Program Design Paradigms “Bootcamp” Lesson 5.4 TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AAA © Mitchell.
Patterns of Communication Between Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson 11.1 © Mitchell Wand, This work is licensed under.
Solving Your Problem by Generalization CS 5010 Program Design Paradigms “Bootcamp” Lesson 7.1 © Mitchell Wand, This work is licensed under a.
Converting from Immutable to Mutable Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson 11.4 © Mitchell Wand, This work is licensed under.
The Function Design Recipe CS 5010 Program Design Paradigms “Bootcamp” Lesson 1.1 TexPoint fonts used in EMF. Read the TexPoint manual before you delete.
Examining Two Pieces of Data CS 5010 Program Design Paradigms “Bootcamp” Lesson © Mitchell Wand, This work is licensed under a Creative.
Classes, Objects, and Methods CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.1 © Mitchell Wand, This work is licensed under a Creative.
The Design Recipe using Classes CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.5 © Mitchell Wand, This work is licensed under a Creative.
Generalizing Similar Functions CS 5010 Program Design Paradigms “Bootcamp” Lesson 5.1 TexPoint fonts used in EMF. Read the TexPoint manual before you delete.
Rewriting your function using map and foldr CS 5010 Program Design Paradigms “Bootcamp” Lesson TexPoint fonts used in EMF. Read the TexPoint manual.
Two Draggable Cats CS 5010 Program Design Paradigms “Bootcamp” Lesson TexPoint fonts used in EMF. Read the TexPoint manual before you delete this.
A Case Study: Space Invaders CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative.
Testing Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative Commons Attribution-NonCommercial.
Patterns of Interaction 2: Publish-Subscribe CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed.
Solving Your Problem by Generalization CS 5010 Program Design Paradigms “Bootcamp” Lesson 7.1 © Mitchell Wand, This work is licensed under a.
The Design Recipe using Classes CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative.
Lists vs. Structures CS 5010 Program Design Paradigms “Bootcamp” Lesson © Mitchell Wand, This work is licensed under a Creative Commons.
Callbacks and Interacting Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative.
Testing Mutable Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative Commons.
Generalizing this Design CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative Commons.
The DD  OO Recipe CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.4 © Mitchell Wand, This work is licensed under a Creative Commons Attribution-NonCommercial.
Stateful Objects and Stable Identities CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under.
The Last Lecture CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative Commons Attribution-NonCommercial.
Observerables are not Fields CS 5010 Program Design Paradigms "Bootcamp" Lesson 10.7 © Mitchell Wand, This work is licensed under a Creative.
Using Inheritance to Share Implementations CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under.
Using the List Template CS 5010 Program Design Paradigms “Bootcamp” Lesson TexPoint fonts used in EMF. Read the TexPoint manual before you delete.
Using the List Template CS 5010 Program Design Paradigms “Bootcamp” Lesson 4.2 TexPoint fonts used in EMF. Read the TexPoint manual before you delete this.
Functions vs. Classes CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative Commons.
More linear search with invariants CS 5010 Program Design Paradigms “Bootcamp” Lesson TexPoint fonts used in EMF. Read the TexPoint manual before.
Solving Your Problem by Generalization CS 5010 Program Design Paradigms “Bootcamp” Lesson © Mitchell Wand, This work is licensed under.
Converting from Immutable to Mutable Objects CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed.
Classes, Objects, and Interfaces CS 5010 Program Design Paradigms "Bootcamp" Lesson © Mitchell Wand, This work is licensed under a Creative.
Generalizing Similar Functions
Examining Two Pieces of Data
CS 5010 Program Design Paradigms “Bootcamp” Lesson 5.4
CS 5010 Program Design Paradigms "Bootcamp" Lesson 9.4
CS 5010 Program Design Paradigms “Bootcamp” Lesson 6.2
Generalizing this Design
Callbacks and Interacting Objects
CS 5010 Program Design Paradigms “Bootcamp” Lesson 3.4
CS 5010 Program Design Paradigms "Bootcamp" Lesson 9.3
Patterns of Interaction 2: Publish-Subscribe
Patterns of Interaction 2: Publish-Subscribe
Solving Your Problem by Generalization
A Case Study: Space Invaders
Contracts, Purpose Statements, Examples and Tests
Generalizing Similar Functions
The Iterative Design Recipe
Examining Two Pieces of Data
A Case Study: Space Invaders
CS 5010 Program Design Paradigms “Bootcamp” Lesson 4.1
CS 5010 Program Design Paradigms “Bootcamp” Lesson 3.4
Presentation transcript:

Using Inheritance to Share Implementations CS 5010 Program Design Paradigms "Bootcamp" Lesson 12.1 © Mitchell Wand, This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. Creative Commons Attribution-NonCommercial 4.0 International License 1

Key Points for Lesson 12.2 By the end of this lesson you should be able to: – Identify common parts of class implementations – Generalize these common parts into a superclass – Recover the original classes using inheritance. – Use the template-and-hook pattern 2

The Real Power of Inheritance The flashing-ball example was a good start, but it didn't illustrate the real power of inheritance. The real power of inheritance is that it enables you to abstract common parts of the implementation of similar classes. Let's try a somewhat more substantial example: squares.rkt 3

Video Demo: squares.rkt (7:36) 4

Can we unify the common code? Looking at Square% and Ball%, we see that many of the method definitions have a lot in common. Let's try to move the common parts into a new class, which we'll call DraggableObject%. Then we'll have Square% and Ball% both inherit from DraggableObject%. Let's see what happens: 5

Video Demo: unify-try1 (5:11) 6

Well, that didn't work Well, that didn’t work. Let’s go back and turn some of those functions into methods 7

Video Demo: turn-differences-into- methods.rkt (4:50) 8

What we have accomplished so far So now the only differences between Ball% and Square% are in methods: add-to-scene place-at-left-edge place-at-right-edge would-hit-left-edge? would-hit-right-edge? inside-this? These are the methods that deal with the geometry of squares and balls so naturally they will be different. Everything else is taken care of in the superclass. 9

The Process in Pictures We start with the two classes Ball% and Square%. The black parts are the same and the red parts are different. 10

Ball% = (class* object% () (field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (on-mouse mx my mev)...(inside-this? mx my))) (define/public (on-tick)...(would-hit-left-edge?)...) (define (inside-this? mx my)...) (define (would-hit-left-edge?)...) ) Square% = (class* object% () (field x y) (define size...) (define/public (add-to-scene s)...) (define/public (on-mouse mx my mev)...(inside-this? mx my))) (define/public (on-tick)...(would-hit-left-edge?)...) (define (inside-this? mx my)...) (define (would-hit-left-edge?)...) ) Starting Code 11

Step 1: Turn differing functions into methods The first thing we do is to turn the differing functions into methods. Each call (f arg) is replaced by (send this f arg). This only comes up because Racket has both methods and functions. If we were in a language where everything was a method, this wouldn't be an issue. 12

Ball% = (class* object% (field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (on-mouse mx my mev)...(send this inside-this? mx my))) (define/public (on-tick)...(send this would-hit-left-edge?)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) Square% = (class* object% (field x y) (define size...) (define/public(add-to-scene s)...) (define/public (on-mouse mx my mev)...(send this inside-this? mx my))) (define/public(on-tick)...(send this would-hit-left-edge?)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) Turning differing functions into methods Ball% = (class* object% () (field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (on-mouse mx my mev)...(inside-this? mx my))) (define/public (on-tick)...(would-hit-left-edge?)...) (define (inside-this? mx my)...) (define (would-hit-left-edge?)...) ) Square% = (class* object% () (field x y) (define size...) (define/public (add-to-scene s)...) (define/public (on-mouse mx my mev)...(inside-this? mx my))) (define/public (on-tick)...(would-hit-left-edge?)...) (define (inside-this? mx my)...) (define (would-hit-left-edge?)...) ) 13

Step 2: Move Common Methods into a Superclass We move the common methods into a superclass. We can think of the common method in the superclass as an abstraction or generalization of the methods in the classes. 14

Step 3: Specialize by Creating Subclasses In the past, we generalized a set of functions by writing a single function with an extra argument. Depending on the value of the extra argument, we could get back one of our original functions. Now instead of two functions, we have two methods, which differ only by being in two different classes. When we move the method into the superclass, the single method can behave like either of the original two methods. We don't give the generalized method an extra argument. Instead, depending on which class the method is called from, we get back the behavior of one of our original methods. We call this "specialization by subclassing." 15

Specialization in squares.rkt In this example, the on-mouse method in DraggableObj% will behave like the original on-mouse method of Ball% if it is called from Ball%. It will behave like the original on- mouse method of Square% if it is called from Square%. Let's see how this works. 16

Ball% = (class* DraggableObj% (inherit-field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) Square% = (class* DraggableObj% (inherit-field x y) (define size...) (define/method (add-to-scene s)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) Move common methods into superclass DraggableObj% = (class* object% (field x y) (define/public (on-mouse mx my mev)...(send this inside-this? mx my)...)) (define/public (on-tick)...(send this would-hit-left-edge?)...) ) 17

What this accomplishes We can think of the common method in the superclass as an abstraction or generalization of the methods in the classes. In the past, we generalized a set of functions by writing a single function with an extra argument. Depending on the value of the extra argument, we could get back one of our original functions. Now instead of two functions, we have two methods, which differ only by being in two different classes. When we move the method into the superclass, the single method can behave like either of the original two methods. We call this specialization by subclassing. 18

Subclassing in Action The animation on the next slide shows how sending a circle an on-mouse message winds up calling the circle’s version of inside-this? If we sent a square an on-mouse message, then we would wind up calling the square’s version of inside-this?, in exactly the same way. 19

Ball% = (class* DraggableObj% (inherit-field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) DraggableObj% = (class* object% (field x y) (define/public (on-mouse mx my mev)...(send this inside-this? mx my)...)) (define/public (on-tick)...(send this would-hit-left-edge?)...) ) x = 20 y = 30 radius = 5 this = circle1 (send circle1 add-to-scene s) Every object knows its own methods #1 Here's an example of method lookup where inheritance isn't involved 20

Ball% = (class* DraggableObj% (inherit-field x y) (define radius...) (define/public (add-to-scene s)...) (define/public (inside-this? mx my)...) (define/public (would-hit-left-edge?)...) ) DraggableObj% = (class* object% (field x y) (define/public (on-mouse mx my mev)...(send this inside-this? mx my)...)) (define/public (on-tick)...(send this would-hit-left-edge?)...) ) x = 20 y = 30 radius = 5 this = circle1 (send circle1 on-mouse mx my) Every object knows its own methods #2 this still refers to circle1 So circle1's inside-this? method is the one that gets called. 21

We can do the same thing with methods that differ only in small ways. We move the common part of the method into the superclass, and have it refer to the differing parts by calling a method in the subclass. Here's an example and a demo. 4. Use Templates and Hooks to Generalize Similar Methods 22

Before: In DraggableObject%: (abstract add-to-scene) In Ball%: (define/override (add-to-scene s) (place-image (circle radius (if selected? "solid" "outline") "red") x y s)) In Square%: (define/override (add-to-scene s) (place-image (square size (if selected? "solid" "outline") "green") x y s)) abstract creates an abstract method, so that DraggbleObject% will satisfy StatefulWorldObj. An abstract method must be defined by a define/override in every subclass. 23

After: In DraggableObject%: (define/public (add-to-scene s) (place-image (send this get-image) x y s)) (abstract get-image) In Ball%: (define/override (get-image) (circle radius (if selected? "solid" "outline") "red")) In Square%: (define/override (get-image) (square size (if selected? "solid" "outline") "green")) add-to-scene is now in the superclass. It uses an abstract method called get- image to retrieve the image. Each subclass must provide a definition for get-image. 24

Video Demo: turn-differing fields into methods.rkt (2:36) 25

This is the Template and Hook pattern The superclass has incomplete behavior. – Superclasses leave hooks to be filled in by subclass. Parameterize a superclass by inheritance Subclasses supply methods for the hooks; these methods are called "at the right time" This is how "frameworks" work. A framework typically consists of a large set of general-purpose classes that you specialize by subclassing. Each subclass contains special purpose methods that describe the specialized behavior of objects of that subclass. big-bang is sort of like this: you tell it what the hook functions are for each event and it calls each function when the event occurs. 26

Yet another way to share fields Create an init-field in the superclass Initialize it from the subclass, using super-new. This is useful for constants that are different in different subclasses. See 12-6-promote-similar-fields.rkt in the Examples folder (also pattern on next slide). 27

Summary: 3 ways to share fields (define super% (class … (init-field x) …x…)) (define sub1% (class super% … (super-new) (inherit-field x) …x…)) 28 Initialize in superclass, inherit into subclass: (define super% (class … (init-field x) (abstract get-x) …(send this get-x)…)) (define sub1% (class super% … (super-new) (init-field x) (define/override (get-x) x) …x…)) Initialize in subclass, access via hook method: (define super% (class … (init-field x) …x…)) (define sub1% (class super% … (super-new [x “this is sub1”]) …x…)) Initialize in superclass:

Summary: Recipe for generalizing similar classes 1.Turn differing functions into methods 2.Move identical methods into a superclass 3.Specialize by subclassing 4.Create hooks to generalize similar methods 29

Summary of the Files Study the relevant files in the examples folder: – 12-2-squares.rkt – 12-3-unify-try1.rkt – 12-4-turn-differences-into-methods.rkt – 12-5-unify-similar-methods.rkt – 12-6-promote-differing-fields.rkt – 12-7-after-review.rkt Here I’ve cleaned up and produced the file as it might appear after Step 6: Program Review. Our design allows for the possibility of multiple boxes in the world, so in 12-7 I’ve done that, too. Do some diffs so you see exactly what changes between one version and the next. 30

Next Steps Study the relevant files in the examples folder: – Do some diffs so you see exactly what changes between one version and the next. If you have questions about this lesson, ask them on the Discussion Board Go on to the next lesson 31