1 / 40

Implications of Inheritance in Software Language Engineering (CSci.658)

Lecture notes discussing the impact of inheritance on programming language features, polymorphic variables, and memory allocation in Java and C++. Accompanies Chapter 11 of Timothy Budd's textbook.

bvail
Download Presentation

Implications of Inheritance in Software Language Engineering (CSci.658)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CSci 658Software Language EngineeringImplication of InheritanceSpring Semester 2018Lecture Notes

  2. Implications of Inheritance (Budd's UOOPJ, Ch. 11) This is a set of slides to accompany chapter 11 of Timothy Budd's textbook Understanding Object-Oriented Programming with Java Updated Edition (Addison-Wesley, 2000) Created: 14 Aug 2004; Revised: 11 Mar 2010; 13 Feb 2018

  3. Idealization of is-a Relationship A TextWindowis-aWindow TextWindow subclasses Window – ideally: • All behavior of Window present in instances of TextWindow • Variable declared as Window should be able to hold value of type TextWindow Unfortunately, practical programming language implementation issues complicate this idealized picture. 1

  4. Impact of Inheritance on Other Language Features Support for inheritance and principle of substitutability impacts most aspects of a programming language • Polymorphic variables needed • Polymorphic variable is declared as one type but actually holds value of subtype • Polymorphic variables better if objects allocated on heap rather than stack – storage requirements vary among subtypes • Heap allocation • Makes reference (pointer) semantics more natural than copy semantics for assignment and parameter passing • copy address of object rather than value • Makes reference semantics more natural for object identity testing – compare addresses – separate operator for object value equality • Requires storage management – reference semantics makes manual allocation difficult – garbage collection encouraged 2

  5. Polymorphic VariablesClass Shape class Shape { public Shape (int ix, int iy) { x = ix; y = iy; } public String describe() { return "unknown shape"; } protected int x; protected int y; } 3

  6. Polymorphic VariablesClass Square class Square extends Shape { public Square(int ix, int iy, int is) { super(ix, iy); side = is; } public String describe() { return "square with side " + side; } protected int side; } 4

  7. Polymorphic VariablesClass Circle class Circle extends Shape { public Circle (int ix, int iy, int ir) { super(ix, iy); radius = ir; } public String describe() { return "circle with radius " + radius; } protected int radius; } 5

  8. Polymorphic VariablesClass ShapeTest class ShapeTest { public static void main(String[] args) { Shape form = new Circle(10, 10, 5); System.out.println("form is " + form.describe() ); } } • Output of ShapeTest: form is circle with radius 5 6

  9. Polymorphic Variables Class CardPile from Solitaire public class CardPile { ... } class SuitPile extends CardPile { ... } class DeckPile extends CardPile { ... } class DiscardPile extends CardPile { ... } class TablePile extends CardPile { ...} 7

  10. Polymorphic VariablesClass Solitaire from Solitaire Example public class Solitaire { ... static public CardPile allPiles [ ]; ... public void init () { // first allocate the arrays allPiles = new CardPile[13]; ... allPiles[0] = deckPile = new DeckPile(335, 30); allPiles[1] = discardPile = new DiscardPile(268, 30); for (int i = 0; i < 4; i++) allPiles[2+i] = suitPile[i] = new SuitPile(15 + (Card.width+10) * i, 30); for (int i = 0; i < 7; i++) allPiles[6+i] = tableau[i] = new TablePile(15 + (Card.width+5) * i, Card.height + 35, i+1); } } 8

  11. Polymorphic VariablesClass SolitaireFrame from Solitaire private class SolitaireFrame extends Frame { ... public void paint(Graphics g) { for (int i = 0; i < 13; i++) allPiles[i].display(g); } } 9

  12. Memory Allocation in Programming Languages • Static allocation • Stack-based allocation • Heap-based allocation 10

  13. Stack-based Memory Allocation Memory allocated dynamically on runtime stack • Memory allocation/release tied to procedure entry/exit • Space requirement determined at compile time based on static types • Advantage: efficient • all local variables allocated/deallocated as a block (activation record) • Disadvantage: polymorphic variable size not known at compile time • objects stored may vary during execution 11

  14. Heap-based Memory Allocation Memory allocated dynamically from free memory area • Memory allocation/release not tied to procedure entry/exit • Space requirement determined at run-time based using dynamic considerations – size known when allocated • Allocated objects accessed by indirection through a pointer (reference in Java) • Advantage: supports polymorphic variables • values can be pointers to object on heap • Disadvantage: considered less efficient than stack-based 12

  15. Memory Allocation in Java • All object variables hold pointers to heap-allocated objects – fixed size on stack, differing sizes on heap • Variable of type Shape holds address of object on heap • Polymorphic variables thus easy to implement • Assignment of Square instance to Shape variable means new address stored • Primitive type variables hold values, copy on assignment, not polymorphic 13

  16. Memory Allocation in C++ • Variables stored on stack • Enough space allocated to hold instance of actual declared type • Variable of type Shape holds actual object • "Ordinary" variables are not polymorphic • Assignment of Square instance to Shape variable means object copied with extra field sliced off – no longer Square • Pointer variables hold addresses of objects • Support polymorphism • Assignment of Square pointer to Shape pointer variable means new address stored • Objects may be allocated on heap (or on stack or statically) • Care must be taken with pointers to deallocated objects on stack (or in heap memory) 14

  17. Copy versus Reference Semantics • Copy semantics • Assignment copies entire value of right side to left-side variable • Two values are independent; changes to one do not affect the other • Examples: Java assignments to primitive variables, C++ assignments to non-pointer variables • Reference (pointer) semantics • Assignment changes left-side variable to refer to right-side value • Two references same value; if value is changed, it can be observed using either reference • Examples: Java assignments to object variables C++ assignments to pointer variables. 15

  18. Java Reference Semantics Example public class Box { public Box() { value = 0; } public void setValue(int v) { value = v; } public int getValue() { return value; } private int value; } 16

  19. Java Reference Semantics Example Example (cont.) public class BoxTest { static public void main(String[] args) { Box x = new Box(); x.setValue(7); // sets value of x Box y = x; // assign y the same value as y y.setValue(11); // change value of y System.out.println("contents of x " + x.getValue()); System.out.println("contents of y " + y.getValue()); } } • After y = x, both x and y in BoxTest refer to the same object Call y.setValue(11) thus changes object referred to by both x and y Message getValue() thus returns same value (11) for both x and y 17

  20. Creating Copies in Java • If need copy, explicitly create it Box y = new Box(x.getValue()); • If commonly need copy, provide copy-creating method public class Box { ... public Box copy() { Box b = new Box(); b.setValue(getValue()); return b; } // return (new Box()).setValue(getValue()) ... } and use method when needed Box y = x.copy(); 18

  21. Creating Copies in Java • Copy constructors are sometimes useful public class Box { ... public Box(Box x) { value = x.getValue()); } ... } • Base class Object has protected method clone() that creates bitwise copy of receiver • Interface Cloneable denotes objects that can be cloned – no methods in interface, just tag • Objects needed by some API methods 19

  22. ExampleJava Clones Make Box a Cloneable object • Implement interface Cloneable • Override method clone() (which returns type Object ) • Make clone() public 20

  23. ExampleJava Clones (cont.) public class Box implements Cloneable {public Box() { value = 0; } public void setValue(int v) { value = v; } public int getValue() { return value; } public Object clone() { return (new Box()).setValue(getValue()); } private int value; } 21

  24. ExampleJava Clones (cont.) public class BoxTest { static public void main(String[] args) { Box x = new Box(); x.setValue(7); // sets value of x Box y = (Box) x.clone(); // assign copy of x to y y.setValue(11); // change value of y System.out.println("contents of x " + x.getValue()); System.out.println("contents of y " + y.getValue()); } } • Values 7 and 11, respectively, would be printed by BoxTest 22

  25. Shallow versus Deep Copying • Suppose values being held by Box objects are themselves objects of type Shape(instead of int) • Box's clone() would not copy Shape object • Clones would both refer to same Shape object • clone() creates a shallow copy • If internal Shape object also copied, then it is a deep copy • Box's method clone() could call Shape's clone() operation • Decide whether shallow or deep copy is needed for application 23

  26. Parameter Passing as Assignment • Parameter-passing is assignment from argument to parameter • Java primitive values are passed by value from argument to parameter – copy semantics • Modification of parameter just local, no effect on argument • Java object variables are passed by reference from argument to parameter – reference semantics Note • Value of reference is copied from argument to parameter • Modification of parameter's internal state is change to argument 24

  27. Parameter Passing as Assignment Example public class BoxTest { static public void main (String[] args) { Box x = new Box(); x.setValue(7); // sets value of x sneaky(x); System.out.println("contents of x " + x.getValue()); } static void sneaky(Box y) { y.setValue(11); } } • Value 11 would be printed by BoxTest 25

  28. Equality Testing Primitive Types • How to test whether two values of same primitive type are equal? • Test whether their values are identical, i.e., same bits • Java: x == y • What about equality of values of different primitive types? • In general, will not pass type checker unless well-accepted conversion between • Java: numeric types converted and compared, but otherwise mismatched types means inequality 26

  29. Equality Testing Object Identity • Some languages compare the values; others, compare pointers (references) • Java uses pointer semantics, i.e., tests object identity Java == tests object identity Integer x = new Integer(7); Integer y = new Integer(3 + 4); if (x == y) System.out.println("equivalent") else System.out.println("not equivalent") • Output is "not equivalent" 27

  30. Equality Testing Object Identity (cont.) Objects x and y physically distinct but same value internally • Java type checker • Disallows comparison of unrelated object types with == • Can compare if one an ancestor of other eg. Circle x = new Circle(10, 10, 5); Shape y = new Square(10, 10, 5); Shape z = new Circle(10, 10, 5); • Above x == y and x == z pass type checking, but neither returns true • null is of type Object; can be compared for equality with any object 28

  31. Equality Testing Object Value Equality • Java Object class has equals(Object) that checks for object identity by default eg. Circle x = new Circle(10, 10, 5); Shape y = new Square(10, 10, 5); Shape z = new Circle(10, 10, 5); … if (x.equals(y)) System.out.println("equivalent"); else System.out.println("not equivalent") ; • Output is “not equivalent" 29

  32. Equality Testing Object Value Equality (cont.) Can override equals() to get more appropriate definition class Circle extends Shape { ... public boolean equals(Object arg) { return arg instanceof Circle && radius == (((Circle)arg).radius); } // more compact above than textbook example } • Above c.equals(d) iff c and d are both Circles with same radius regardless of location • Should override equals() if object contains other objects 30

  33. Equality Testing Object Value Equality (cont.) • Be careful with asymmetric equality comparisons Suppose override equals() in Shape class Shape { ... public boolean equals(Object arg) { if (arg instanceof Shape) { Shape s = (Shape)arg; return x == s.x && y == s.y ; } else return false; } } But not in subclass Square 31

  34. Equality Testing Object Value Equality (cont.) Now consider Square s = new Square(10,10,5); Circle c = new Circle(10,10,5); if (s.equals(c)) // true, uses Shape method System.out.println("square equal to circle"); if (c.equals(s)) // false, uses Circle method System.out.println("circle equal to square"); 32

  35. Equality Testing Changing Method Arguments • For equality testing, it might useful to change types of method arguments class Shape { ... public boolean equals (Shape s) { return false; } } class Circle extends Shape { ... public boolean equals (Circle c) { ... } } class Square extends Shape { ... public boolean equals (Square sq) { ... } } 33

  36. Covariance and Contravariance • Covariant • An argument or return value made more specialized • Type replaced by descendant of original type • Contravariant • An argument made more general • Both can destroy is-a relation, have tricky semantics • Most languages forbid both • Java and C++ forbid • Eiffel supports covariance 34

  37. Storage Deallocation • Polymorphic variables lead naturally to heap-based allocation • Heap-based allocation requires a storage deallocation mechanism • Two approaches: • Explicit deallocation by programmer • Implicit deallocation by runtime system 35

  38. Storage DeallocationExplicit Deallocation by Programmer • Programmer must return unneeded memory to system • Examples: C++ delete, Pascal dispose • Advantage: efficiency • Disadvantages • Attempted use of memory not yet allocated or already freed • Multiple freeing of memory • Freeing of memory that is still needed • Memory leak – allocated memory is never released 36

  39. Storage DeallocationImplicit Deallocation by Runtime System • System detects when data unneeded, automatically recovers memory • Garbage collection • Examples: Java, Smalltalk, Perl • Advantage • Safety and convenience • Disadvantage • Relative inefficiency / loss of programmer control 37

  40. Acknowledgement This work was supported by a grant from Acxiom Corporation titled “The Acxiom Laboratory for Software Architecture and Component Engineering (ALSACE).” 38

More Related