Скачать презентацию Attached types and their application to three open Скачать презентацию Attached types and their application to three open

f6fcfb1b39c39dc29a71a04f4ee6cdd0.ppt

  • Количество слайдов: 27

Attached types and their application to three open problems of object-oriented programming Bertrend Meyer Attached types and their application to three open problems of object-oriented programming Bertrend Meyer ETH Zurich and Eiffel Software Itay Maman 236803 Seminar lecture, 8 November 2005 1

Motivation Exception in thread Motivation Exception in thread "AWT-Event. Queue-0" java. lang. Null. Pointer. Exception at my. program. Main. Window$1. action. Performed(Main. Window. java: 33) at javax. swing. Abstract. Button. fire. Action. Performed(Unknown Source) at javax. swing. Abstract. Button$Handler. action. Performed(Unknown Source) at javax. swing. Default. Button. Model. fire. Action. Performed(Unknown Source) at javax. swing. Default. Button. Model. set. Pressed(Unknown Source) at java. awt. Component. process. Mouse. Event(Unknown Source) Guarantee that in x. f(a 1, a 2, . . ), the receiver, x, will always denote an object §This talk: • Presents Meyer’s notion of non-null types • (Implemented in the Eiffel language) • We will use Java-like syntax 2

Thoughts on static typing • Let’s consider x. f() • Static typing: Ensures that Thoughts on static typing • Let’s consider x. f() • Static typing: Ensures that x will point to an object • that “understands” the message f() But, x could be null § null does not understand f() § => null pointers are “holes” in the static typing system • Elimination of null pointers is a typing issue § (Not a data analysis issue) 3

null, what is it good for? • Special value § Indicating end-of-file, a missing null, what is it good for? • Special value § Indicating end-of-file, a missing value, etc. • Delayed initialization of fields § In a word-processor, there is no document object until the user opens a file § Two (or more) mutually dependent objects • Recursive data structures § Recursive data structures • Q: Can we find an alternative to null values? 4

Null-safety in Eiffel (A new mechanism, recently proposed) • Non-null type: A type T Null-safety in Eiffel (A new mechanism, recently proposed) • Non-null type: A type T has no null value § This is the default • Null type: ? T is a super type of T which has the null value • Only non-null types allow invocation of methods § The same goes for field access • Automatic conversion: T -> ? T • Checked conversion: ? T -> T 5

A non-null program public class Printer { private Print. Writer out = System. out; A non-null program public class Printer { private Print. Writer out = System. out; public Printer(? Print. Writer pw) { if( (Print. Writer o = ) pw) { out = o; Downcast+assign expression: o. flush(); • Check non null } • Check dynamic type } • Assign to a local variable public void print(Object obj) { out. println(obj. to. String()); } } 6

An equivalent program public class Printer { private Print. Writer out = System. out; An equivalent program public class Printer { private Print. Writer out = System. out; public Printer(Print. Writer pw) { Object temp = pw; if(temp instanceof Print. Writer) { Print. Writer o = (Print. Writer) temp; out = o; o. flush(); } } public void print(Object obj) { out. println(obj. to. String()); } } 7

CAP: Certified Attachment Patterns public class Int. List { private ? Int. List tail; CAP: Certified Attachment Patterns public class Int. List { private ? Int. List tail; private int n; public Int. List(int n, ? Int. List tail) {. . . } public static void print(? Int. List list) { while(list != null) { System. out. println(list. n); list = tail; } } } • The expression list. n is (statically) null-safe § Look at the loop condition! § This is a CAP of list 8

CAPs • Definition: CAP(x) § A segment of code, where x is ensured to CAPs • Definition: CAP(x) § A segment of code, where x is ensured to be non-null by some null test • x – An expression whose type is nullable • CAPs eliminate many downcast+assign expression § => Simple, intuitive code • Currently there are several standard CAPs § A compiler implementation cannot add a new CAP § Note that CAP for fields are more restricted • Scope is limited to first instruction after the null test 9

Standard CAPs for locals // x is a nullable local variable: ? X x; Standard CAPs for locals // x is a nullable local variable: ? X x; while(x != null) { x. f(); x. g(); x = h(); } if(x == null) {. . . } else { x. f(); x. g(); x = h(); } x = new X(); x. f(); x. g(); x = h(); b = (x != null) && (x. f() == x. g()); b = (x == null) || (x. f() == x. g()); assert x != null; x. f(); x. g(); x = h(); § If x is a field, only x. f() is legal 10

Soundness • Assignment § ? T -> T is illegal § null -> T Soundness • Assignment § ? T -> T is illegal § null -> T is illegal • Initialization § Formal arguments • Are always assigned upon method invocation § Local variables • Compiler already ensures proper initializaion § Fields… 11

Soundness: Fields • The problem: Ensuring non-null initialization of fields § Historically, fields are Soundness: Fields • The problem: Ensuring non-null initialization of fields § Historically, fields are initialized with null • Meyer’s approach: § Three distinct solutions… 12

Solution 1/3: Self initializing types § Field Y. x is lazily initialized on first Solution 1/3: Self initializing types § Field Y. x is lazily initialized on first access • Only if not previously initialized • Applicable if X has a default constructor class X { public X() { } public void f() { } } class Y { private X x; public void h() { x. f(); // Lazy initialization: // Invoke default constructor of x } } 13

Solution 2/3: Self initializing fields • Field Circle. rect is lazily initialized on first Solution 2/3: Self initializing fields • Field Circle. rect is lazily initialized on first access § Only if not previously initialized § Initialization block added to the field’s definition class Rectangle { Rectangle(int x 0, int y 0, int x 1, int y 1) {. . . } } class Circle { private final int cx, cy, r; private Rectangle rect { return new Rectangle(cx-r, cy-r, cx+r, cy+r); } public Circle(int cx, int cy, int r) {. . . } public Rectangle get. Rect() { return rect; } } 14

Solution 3/3: Initialization by constructors • The last case: § Non-null fields w/o initialization Solution 3/3: Initialization by constructors • The last case: § Non-null fields w/o initialization block § (The first two solutions do not apply) • The solution: § Initialization by every constructor § Statically enforced by the compiler 15

Soundness: Summary • Assignment § Cannot set a null-safe entity to null • Initializaion Soundness: Summary • Assignment § Cannot set a null-safe entity to null • Initializaion § Arguments: Always initialized § Local variables: Initialization analysis § Fields • Non null types => Default constructor • Non null fileds = > Initialization block • Otherwise => Explicitly by all constructors 16

Generics: The problem • Where’s the error here? class Cell<T> { private T value; Generics: The problem • Where’s the error here? class Cell { private T value; public Cell() { } public Cell(T t) { value = t; } public T get() { return value; } } void main() { Cell c 1 = new Cell(); Cell c 2 = new Cell("abc"); Cell c 3 = new Cell(); Cell c 4 = new Cell("abc"); } • Generic code may break null-safety § When the actual generic type is non-null 17

Generics: Solution? • The solution: Use self-initializing types § If Cell<T> uses T in Generics: Solution? • The solution: Use self-initializing types § If Cell uses T in a context where it hasn’t been provably initialized § => T must be self-initializing § This is statically enforced 18

Design by contract (1/2) • Eiffel features design by contract § Pre/Post conditions, class Design by contract (1/2) • Eiffel features design by contract § Pre/Post conditions, class invariants, … • How does it interact with non-null types? // This is “old” Eiffel code String nice. String(Object o) require o != null; ensure result != null; { if(o. to. String() == null) return "<>"; return "<" + o. to. String() + ">"; } • We can define new CAPs § Based on pre/post conditions 19

Design by contract (2/2) • In “New” Eifflel, we can use non-null types § Design by contract (2/2) • In “New” Eifflel, we can use non-null types § And get rid of many pre/post conditions // This is “new” Eiffel code String nice. String(Object o) { if(o. to. String() == null) return "<>"; return "<" + o. to. String() + ">"; } 20

Covariant input arguments • “old” Eiffel allow covariant input arguments § => Polymorphic calls Covariant input arguments • “old” Eiffel allow covariant input arguments § => Polymorphic calls may fail at run time • “New” Eiffel is a bit different… • The hierarchy: § Privileged. Account extends Account § Privileged. Customer extends Customer • Has a get. Interest() method 21

A covariant program • Covariance is now allowed only if the argument is nullable A covariant program • Covariance is now allowed only if the argument is nullable class Account { float interest = 0. 03; Customer cus; void set. Customer(Customer c) { cus = c; } } class Privileged. Account { void set. Customer(? Privileged. Customer c) { super. set. Customer(c); // Can we invoke c. get. Special. Interest() ? if((Privileged. Customer pc = ) c) } } interest = pc. get. Interest(); } } • This mechanism is too flexible 22

Comments (1/2) • Open questions § § Covariance: CAP can bypass the downcast Access Comments (1/2) • Open questions § § Covariance: CAP can bypass the downcast Access to fields from constructor code Arrays Generics: Why not require a non-null actual type parameter • Currently requires self-initialization • Expressions such as if(list. next != null) are quite useful § With non-null being the default this becomes a bug 23

Comments (2/2) • Downcast+Assign is used in two contexts § Null safety: Check-not-null and Comments (2/2) • Downcast+Assign is used in two contexts § Null safety: Check-not-null and assign to a local § Covariance: Downcast to a restricted set of types § Why not split to two constructs? • Not trying to be backward compatible 24

Further discussion • Null safety in standard Java § Just use the final keyword Further discussion • Null safety in standard Java § Just use the final keyword • Recursive data structures § Can we replace null values with “null objects” ? 25

Using null-objects (1/2) // A null terminated list int max = -99999; for(Node n Using null-objects (1/2) // A null terminated list int max = -99999; for(Node n = start(); n != null; n = n. next) max = Math. max(max, n. value); // A null-object terminated list int max = -99999; for(Node n = start(); n. ok(); n = n. next) max = Math. max(max, n. value); 26

Using null-objects (2/2) Class Node {. . . public int max() { return Math. Using null-objects (2/2) Class Node {. . . public int max() { return Math. max(value, next. max()); } } Class Null. Node { public int max() { return -99999; } } 27