Assertions Prasun Dewan Comp 114 Assertions Declare some
- Slides: 148
Assertions Prasun Dewan Comp 114
Assertions • Declare some property of the program • Potentially useful for – specification – testing – formal correctness – documentation
Compile time vs. runtime properties • Some assertions language supported – Compile time • String s = next. Element() – Runtime • ((String) next. Element()) – Asserting type properties of object. – Assertions describe runtime properties
Application-independent vs. dependent • Language can provide us with fixed number of application-independent assertions. • Cannot handle – First character of String is a letter. – Letter concept not burnt into language. • Class Character defines it – Innumerable assertions about letters possible • Second elements of string is letter. • Third element of string is letter. • Need mechanism to express arbitrary assertions
Assertions vs. Exceptions • Wrong assertion results in exception. • Wrong class cast leads to class cast exception.
Reasons for exceptions • User error – Programmer cannot prevent it • Internal error – Programmer can prevent • Assertions catch internal errors.
Reasons for assertions • Why catch internal errors via assertions? • Alternative: Make test runs and look at output.
Finite test runs • Some errors not exhibited in test runs. – Inconsistent string not printed because of user option.
Late detection • Output produced much after the cause – Storing an inconsistent string causes erroneous output when the string is matched not when it is stored.
Complex output • May not know what the output is, but know the relationship between input and output – (123. 345 * 789. 123 ) / 123. 345 == 789. 123 – Number is divisible by a prime factor
No manifestation in output • Some errors have to do with efficiency. – Storing duplicate items in a set. • Not exhibited in output
Example Assertion { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) Our own mathematical syntax to be mapped to Java later
Definition • Example { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) • Statement regarding – State of program (variable values) – Program counter (currently executing statement) • PC implicit by putting assertion next to a statement – Specifies Boolean expression involving selected program variables – Assertion fails if boolean expression false – Not all program variables named • X unnamed above • Does not care about unnamed variables
Role of Assertions • Debugging – Exception thrown if assertion fails • Documentation // detailed prime factor computation code …. assert (number % prime) == 0 • Specification – Assertion defined desired result of the code to be implemented • Formal correctness – Can prove if assertion met by code. – Need assertions regarding language constructs
Recording Variables {X = X + 1} assert ? ? ? • Cannot say: {X = X + 1} assert X == X + 1; • Introduce recording variable {old. X = X; X = X + 1} assert X = old. X + 1 • Special variables needed to make assertions sometimes
Preconditions and Postconditions • Precondition assert (x !=0) { y = 10/x; z = 5} assert (y == 10/x) & (z == 5) – What is expected before statement(block) execution • Postcondition – What is guaranteed after statement(block) if precondition met • Together define a contract
Alternative syntax • Both conditions placed before statement block. pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}
Incorrect precondition? x = 0; pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5} • Precondition may not be satisfied by previous incorrect statement. • Yet it is a correct precondition
Alternative precondition • Some assertions imply others – x > 0 x !=0 pre (x > 0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5} • Implied assertion is considered weaker. • Can always replace precondition with a stronger one. • Prefer weakest precondition – Requires fewest assumptions. – Statement can be used in more contexts – Better documentation
Alternative postcondition • Some assertions imply others – y == 10/x & (z == 5) => z == 5 pre (x != 0) post (z == 5) { y = 10/x; z = 5} • Can always replace postcondition with a weaker one • Prefer strongest postcondition – More detailed documentation – Can be used in more contexts • Can be followed by statements with stronger preconditions.
Too strong Comp 114 • pre arrays, loops, procedures • {Take Comp 114} • post objects, inheritance, trees, recursion, assertions, composite, iterator, visitor pattern • pre arrays, loops, procedures, objects, inheritance • {Take Comp 114} • post recursion Too weak
Course Analogy • Preconditions – Declared course prerequisite • Post conditions – Advertised objectives • Stronger precondition – Does not allow some students to enroll • Weaker post conditions – Does not allow enrollment in future courses
Strongest Postcondition? • Says nothing about x. pre (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}
Strongest Postcondition • Strongest post condition given pre (x !=0) the precondition post (y == 10/x) & (z == 5) & (x != 0) • The stronger the pre condition, { y = 10/x; z = 5} stronger the post condition.
Alternative weakest/strongest pair Stronger precondition pre (x > 0) post (y == 10/x) & (z == 5) & (x > 0) & (y > 0) { y = 10/x; z = 5} Stronger postcondition
Multiple valid pairs • Weakest precondition relative to post condition. • Strongest post condition relative to pre condition. • A statement not associated with a unique pair that is best. • Strengthening the precondition strengthens the post condition • What is the “right pair? ”
Two approaches • Start with a precondition – Find the strongest postcondition we can prove. • Start with a post condition – Find the weakest precondtion for it.
Theoretical specification point of view • Specify the result needed as a post condition. • Identify the weakest precondition needed to obtain the result. • Write a program that satisfies the pair.
Reality specification point of view • Based on what you can assume you change your expectations. • Iterative process.
Debugging/specification/ documentation point of view • Precondition of a statement should be weakest one necessary for “correct” operation of program. – Correct means no exception. • A statement that is not equivalent should not have the same pre and post condition
Debugging/specification/ documentation point of view pre (x >0) post (y == 10/x) & (z == 5) & (x > 0) { y = 10/x; z = 5} pre (x >0) post (y == 10/x) & (z == 5) & (x > 0) { y = 10/x; z = 5; x = abs(x) + 1} Statements are not equivalent
Debugging/ specification/ documentation point of view Best pre and post conditions pre (x !=0) post (y == 10/x) & (z == 5) & (x != 0) { y = 10/x; z = 5}
Proving programs correct point of view • Precondition can be stronger than one that is the best one for the statement from debugging/specification/documentation point of view • Allows us to derive pre and post conditions of containing statement/program
Program correctness proof pre post (x == 1) {x = 1} pre (x == 1) post (y == 10/x) & (z == 5) & (x == 1) { y = 10/x; z = 5}
Program correctness proof pre post (y == 10/x) & (z == 5) & (x == 1) {x = 1; y = 10/x; x= 5}
Changeable assertions • What we assert about a statement (to prove program correct) may depend on what is executed before it. • Need facilities to change assertions easily. • Proxies explained later address this.
Weakest possible condition • • • Implied by anything true p true If p is true then true is true. But true is always true. So p can be any boolean expression.
Strongest possible condition • • Implies anything false p If false is true then p is true But false is never true. So any p is implied. “I will give you a million dollars when hell freezes over”
Important equivalence • P Q !P | Q • P true !P | true • false Q !false | Q true
Asserting false switch c { case ‘a’: … case ‘b’: … default: assert false } Unreachable statement
Invariant • True before and after statement pre (x !=0) post (y == 10/x) & (z == 5) & (x != 0) { y = 10/x; z = 5}
Separately declared • List invariant separately inv (x !=0) post (y == 10/x) & (z == 5) { y = 10/x; z = 5}
Invariants for debugging purposes • Should never be false – False strongest invariant of all statements. – But not best for a reachable statement as it does not convey useful information – Never assert it for reachable statements if assertion not done for program proofs. • Should never involve recording variables – recording variables describe how program variables change – invariants describe how these variables do not change
Loop Invariant sum = 0; j = 0; while (j < n) { j++; sum = sum + j; } • Holds true before and after each loop iteration, that is, before and after each execution of loop body.
Loop Invariant • Holds true before and after each loop inv (sum = 0 j k) & (j <= n ) & (j >= 0) iteration, that is, sum = 0; before and after each j = 0; execution of loop while (j < n) { body. j++; sum = sum + j; }
Method assertions invariant x != 0 post (y == 10/x) & (z == 5) & (x != 0) void m () { y = 10/x; z = 5; } • Preconditions, postconditions, invariants associated with method body
Class assertions public class C { int x =0; int y = 1; public void increment. XAnd. Y () { increment. X(); increment. Y(); } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } } • Preconditions, postconditions, invariants shared by all public methods of class
Class assertions inv y == x + 1 public class C { int x =0; int y = 1; public void increment. XAnd. Y () { increment. X(); increment. Y(); } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } } • Preconditions, postconditions, invariants shared by all public methods of class
Expressing Assertions • Natural language – All array elements are not odd. – All array elements are either odd or positive. – Easy to read but ambiguous. • Programming language – Library or language constructs – Executable, unambiguous but language-dependent and awkward • Useful for debugging • Specification cannot be done before language decided. • Mathematical language – Uambiguous, time tested, convenient but not executable
Propositional Calculus • Logic operators • not, and, or • We will use Java syntax. • Quantifiers – Universal ( ) – Existential ( ) • Propositional variables • Program • Others: Recording, Quantifier • Propositions – Boolean expressions involving operators, variables, and quantifiers • Simple/quantified propositions – Do not use/use quantifiers
Propositional Algebra • Calculus based on algebra • Algebra defines – Arithmetic operations – Relations operations – We will use Java syntax
Example Propositions • Simple propositions – – True False X>6 (X > 6 ) & (Y < 2) • Quantified – j: 0 <= j < b. size() : b. element. At(j) != null • All elements of B are not null – j: 0 <= j < b. size(): b. element. At(j) != null • At least one element of B is not null.
Quantified Propositions • Quantified – j: 0 <= j < b. size(): b. element. At(j) != null • General form: – Qx: D(x): P(x) – Q is either or quantifier – X is quantified variable – D(x) is domain description – P(x) is sub-proposition • Sub-proposition – Simple or quantified proposition in terms of quantifier • Domain – A collection of values used in sub-proposition evaluation – b. element. At(0), … b. element. At(B. size() – 1 • Domain description – Describes domain using quantified variable
Expressing Assertions in Java • Write your own code. • Libraries • Language support – Does not support quantifiers – Works for 1. 4 – You have 1. 3
Assertion Failed Exception package assertions; public class An. Assertion. Failed. Exception extends Runtime. Exception { public An. Assertion. Failed. Exception () {}; public An. Assertion. Failed. Exception (String init. Value) { super (init. Value); } } • Thrown when assertion fails • Unchecked because internal error • Can subclass it for specific assertions • Will use message in examples
Assert methods package assertions; import java. util. Enumeration; public class An. Asserter { public static void assert (boolean proposition, String message) throws An. Assertion. Failed. Exception { if (!proposition) throw new An. Assertion. Failed. Exception (message); } public static void assert (boolean proposition) throws An. Assertion. Failed. Exception { assert (proposition, “”); } • Used for simple assertions }
Using assert //inv (sum = 0 j k) & (j <= n ) & (j >= 0) sum = 0; j = 0; while (j < n) { j++; sum = sum + j; } • Must write our boolean expression that is passed to assert – public static int sum (int from, int to) { … } • Must code pre/post conditions and invariants as assert calls
Using assert sum = 0; j = 0; //inv (sum = 0 j k) & (j <= n ) & (j >= 0) while (j < n) { An. Asserter. assert (j <= n && j >= 0 && sum == sum(0, j)) j++; sum = sum + j; An. Asserter. assert (j <= n && j > =0 && sum == sum(0, j)) } • Must write our boolean expression that is passed to assert – public static int sum (int from, int to) { … } • Must code pre/post conditions and invariants as assert calls
Class and Method Invariants //inv y = x + 1 • Class invariant public class C { – Encode them as invariants of int x =0; all public methods. int y = 1; public void increment. XAnd. Y () { • Method invariant increment. X(); – Put assert at start and end of increment. Y(); public methods } public int get. X() { return x; } public int get. Y() { return y; } increment. X() { x++; } increment. Y() { y++; } }
Class and Method Invariants //inv y = x + 1 public class C { int x =0; int y = 1; void assert. Class. Invariant{ An. Asserter. assert (y == x + 1); } public void increment. XAnd. Y () { assert. Class. Invariant(); increment. X(); increment. Y(); assert. Class. Invariant(); } public int get. X() { assert. Class. Invariant(); ? ? ? return x; } … } • Class invariant – Encode them as invariants of all public methods. • Method invariant – Put assert at start and end of method Cannot put something after return and return may have side effects (return x++)
Class and Method Invariants //inv y = x + 1 public class C { int x =0; int y = 1; void assert. Class. Invariant{ An. Asserter. assert (y == x + 1); } void internal. Increment. XAnd. Y () { increment. X(); increment. Y(); } public void increment. XAnd. Y () { assert. Class. Invariant(); internal. Increment. XAnd. Y(); assert. Class. Invariant(); } internal. Get. X() { return x; } public int get. X() { assert. Class. Invariant(); int ret. Val = internal. Get. X(); assert. Class. Invariant(); return ret. Val; } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points Asserting proxy method
Multiple exit points char assign. Grade (int score) { if (score >= 50) { grade = ‘P’; return; } else grade = ‘F’; } char asserting. To. Grade (int score) { assign. Grade(score); assert (grade == ‘F’ || grade == ‘P’); } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points
Quantified Assertions • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Goal: – Write general boolean functions that take as arguments encoding of the elements of domain and return true iff proposition is true – Will write separate functions for universal and existential quantifer
Goal package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All (…) { … } public static boolean there. Exists (…) { … } } • Need to fill the …
Problem with inaccessible variables • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • How to describe D(x) and P(x)? – Cannot pass expression string as variables involved have no meaning to library – Will pass one argument describing the domain • Collection of elements – Another argument describing the subproposition to be evaluated for each domain element.
How to describe domain? • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Domain can be – Array, Vector, String. History, … • Need a common interface to describe elements – java. util. Enumeration
Describing the domain package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All ((Enumeration domain, …) { while (domain. has. More. Elements()) … } public static boolean there. Exists ((Enumeration domain, …) { while (domain. has. More. Elements()) … } } An. Asserter. assert(AQuantifier. for. All(B. elements(), …, "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), …, "All elements of B are null"); Need to fill …
How to describe Subproposition • Syntax – Qx: D(x): P(x) – j: 0 <= j < b. size(): b. element. At(j) != null • Cannot pass expression string as variables involved have no meaning to library • But can pass function that evaluates it. – boolean is. Not. Null(Object element) { return element != null; } • Function will be evaluated for each domain element by our libraries
Subproposition as a function package assertions; import java. util. Enumeration; public class AQuantifier { public static boolean for. All (Enumeration domain, (object boolean) sub. Proposition) { while (domain. has. More. Elements()) if (!sub. Proposition (domain. next. Element()) return false; return true; } public static boolean there. Exists ((Enumeration domain, (object boolean) sub. Proposition) { while (domain. has. More. Elements()) if (!sub. Proposition (domain. next. Element()) return true; return false; } } An. Asserter. assert(AQuantifier. for. All(B. elements(), is. Not. Null), "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), is. Not. Null), "All elements of B are null");
How to describe Subproposition package assertions; public interface Element. Checker { public boolean visit (Object element); } • Cannot pass expression string. • But can pass function that evaluates it. – boolean is. Not. Null(Object element) { return element != null; } package visitors; • import assertions. Element. Checker; public class ANon. Null. Checker • implements Element. Checker { public boolean visit(Object element) { return (element != null); • } } Java does not support function parameters But allows object parameters – Object = data + functions All subproposition objects implement same interface • A subproposition object visits each element
Describing the subproposition package assertions; Call import java. util. Enumeration; public class AQuantifier { public static boolean for. All (Enumeration domain, Element. Checker sub. Proposition) { Callback while (domain. has. More. Elements()) if (!sub. Proposition. visit(domain. next. Element())) return false; return true; } public static boolean there. Exists (Enumeration domain, Element. Checker sub. Proposition) { while (domain. has. More. Elements()) if (sub. Proposition. visit(domain. next. Element())) return true; return false; } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new ANon. Null. Checker()), "Some element of B is null"); An. Asserter. assert(AQuantifier. there. Exists(b. elements(), new ANon. Null. Checker()), "All elements of B are null");
Calls vs. Callbacks • Calls – calls from reusing class to reused class • Callbacks – calls from reused class to reusing class. – not to implement a symbiotic relationship – done to service calls
Subproposition accessing vars other than domain elements • • j: 0 <= j < b. size(): b. element. At(j) != a. element. At(0) package visitors; import assertions. Element. Checker; public class ANon. Null. Checker implements Element. Checker { public boolean visit(Object element) { return (element != null); } } No constructor An. Asserter. assert(AQuantifier. for. All(b. elements(), new ANon. Null. Checker()), "Some element of B is null");
Subproposition accessing vars other than domain elements • • j: 0 <= j < b. size(): b. element. At(j) != a. element. At(0) Each external var becomes constructor parameter package visitors; import assertions. Element. Checker; public class An. Inequality. Checker implements Element. Checker { Object test. Object; public An. Inequality. Checker(Object the. Test. Object) { test. Object = the. Test. Object; } public boolean visit(Object element) { return !element. equals(test. Object); } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new An. Inequality. Checker(a. element. At(0))), "Some element of b is equal to a. element. At(0)");
Visitor Pattern • • Some collection C of elements of type T Visitor interface – public interface Element. Checker { public boolean visit (Object element); } – public interface V {public T 2 m (T p); } • One or more traverser methods that use collection and visitor interface to pass one or more collection elements to the method. – public static boolean for. All (Enumeration domain, Element. Checker sub. Proposition) {…sub. Proposition. visit(domain. next. Element()); – traverser 1 (C c, V v) { …v. m(element of C)…} • Implementation of interface whose constructors take as arguments external variables that need to be accessed by the visitor method public class An. Inequality. Checker implements Element. Checker { Object test. Object; public An. Inequality. Checker(Object the. Test. Object) {…} public boolean visit(Object element) {…}; } public class AV 1 implements V { public AV 1 (T 1 p 1, … Tn p. N) { …} public T 2 m (T p) { … } } • Client passes traverser visitor implementation and collection – AQuantifier. for. All(b. elements(), new An. Inequality. Checker(a. element. At(0))); – traverser 1(c, new AV 1(a 1, . . a. N));
Visitor Pattern Collection Interface C with elements of type T component element 1: T uses Traverser 1 element 1: T Traverser 2 Visitor Interface implements Visitor Class 1 Visitor Class 2
Example of Visitor Pattern Enumeration uses component Object for. All() Object there. Exists() Element. Checker implements ANon. Null Checker An. Inequality Checker
Nested Assertions j: 0 <= j < b. size(): k: 0 <= k < b. element. At(j). size(): b. element. At(j). element. At(k) != null package visitors; import assertions. Element. Checker; public class ANon. Null. Checker implements Element. Checker { public boolean visit(Object element) { return (element != null); } } package visitors; import assertions. Element. Checker; public class AFor. All. Checker implements Element. Checker { public boolean visit(Object element) { Enumeration children = ( (Vector) element). elements(); return AQuantifier. for. All(children, new ANon. Null. Checker())); Visiting Hierarchical Structures (Trees) } } An. Asserter. assert(AQuantifier. for. All(b. elements(), new AFor. All. Checker(), "Some leaf-level element of b is null”);
Example of Pattern in Everyday Applications • • • Program tree A visitor for printing all nodes. Another for type checking. Yet another for generating code Do not want to put all of this code in tree class. • In any case, printing should not be in tree.
Java 1. 4 Assertion Support • Assertion. Error exception = An. Assertion. Failed. Exception • assert <boolean expression> = An. Asserter. assert(<boolean expression>, “”); • assert <boolean expression>: <value> = An. Asserter. assert(<boolean expression>, string representation of <value> • Compile option determine if assert is keyword – javac –source 1. 4 models/ACounter. java • Assertions can be dynamically turned on or off for package or Class – java –da: bus. uigen –ea models. ACounter • No support for quantifiers.
Error vs. Exception • Java assertion failure results in Assertion. Error • Subclass of Error rather than Run. Time. Exception • Reasoning: – Convention dictates that Run. Time. Exception should be caught – Should “discourage programmers from attempting to recover from assertion failures. ” • Might do custom reporting, mail error report etc. – Decision was controversial
Modularizing assertion code • How to not clutter regular with assertion code. • How to turn off/change library-based assertion code?
Proxy Methods char assign. Grade (int score) { if (score >= 50) { grade = ‘P’; return; } else grade = ‘F’; } char asserting. To. Grade (int score) { assign. Grade(score); assert (grade == ‘F’ || grade == ‘P’); } • Can define another proxy method that asserts and calls the real method – Keeps asserting code separate – Useful for functions – Useful when multiple exit points
Proxy classes • Put assertion code in special classes that are proxies for real classes. • Factory, factory selectors and factory methods can be used to choose between proxy and regular classes.
Counter package models; public class ACounter implements Counter { int counter = 0; public void add (int amount) { counter += amount; } public int get. Value() { return counter; } }
Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }
Example of Proxy Pattern ACounter implements IS-A implements AChecked Counter
Proxy Pattern Real Subject Class IS-A Proxy Class implements Subject Interface implements
Proxies in everyday apps • Proxy is a stand-in for real subject. • Adds to one or more method implementations • Web proxies – Cache data – Redirect to nearest server • Proxy may – – Log Cache (remote proxy) Provide access control Assert
Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } } Alternative way of doing proxy?
Delegating Proxy • Proxy HAS-A reference to the Subject and not IS-A Subject. • Proxy is called delegator and subject is called delegate
Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }
Example of Delegating Proxy ACounter implements HAS_A AChecked Counter implements Counter
Delegating Proxy Real Subject Class HAS_A Proxy Class implements Subject Interface implements
Inheritance vs. Delegation Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements
OMT (Object Modeling Technique) Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements
Added notation of implements Real Subject Class implements Subject Interface IS-A Proxy Class implements Subject Interface Real Subject Class HAS-A Proxy Class implements
Inheritance vs. Delegation Reused Class Reused Interface Reusing Class Reusing Interface
Inheritance vs. Delegation: Instances Reused Class Reusing Class Reused Class instance Physical component Reusing Class instance
Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }
Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value()b; } }
Inheritance vs. Delegation: Init methods/Constructor Reused Class Reusing Class declares Constructor/init (…) Reused Class Reusing Class declares Constructor/init (delegate, …)
Inheritance vs. Delegation: Super calls Reused Class Reusing Class Reused Class declares Reused method m super. m() declares Method n declares Reused method m delegate. m() Reusing Class declares Method n
Asserting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter extends ACounter { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }
Delegating Proxy-based Counter package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { init(the. Counter); } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }
Inheritance vs. Delegation: Reused Methods Reused Class declares Reused method m Delegation is more work! Reusing Class Reused Class declares Reused method m delegate. m() Reusing Class declares m stub
Abstract class public abstract class An. Abstract. Title. To. Course. Mapper implements Title. To. Course. Mapper { public An. Abstract. Title. To. Course. Mapper() { fill. Courses(); } abstract Regular. Course get. Regular. Course(); abstract Freshman. Seminar get. Freshman. Seminar(); void fill. Courses() { Regular. Course intro. Prog = get. Regular. Course (); Freshman. Seminar lego. Robots = get. Freshman. Seminar(); . . . } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }
Concrete course user public class ATitle. To. Course. Mapper extends An. Abstract. Title. To. Course. Mapper { Regular. Course get. Regular. Course() { return new ARegular. Course(); } Freshman. Seminar get. Freshman. Seminar() { return new AFreshman. Seminar(); } }
Delegate class public class ATitle. To. Course. Mapper. Delegate implements Title. To. Course. Mapper { Course. Factory delegator; public ATitle. To. Course. Mapper. Delegate(Course. Factory the. Delegator) { delegator = the. Delegator; fill. Courses(); } void fill. Courses() { Regular. Course intro. Prog = delegator. get. Regular. Course (); Freshman. Seminar lego. Robots = delegator. get. Freshman. Seminar(); . . . } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }
Concrete course user public class ATitle. To. Course. Mapper. Delegator implements Title. To. Course. Mapper, Course. Factory { public Regular. Course get. Regular. Course() { return new ARegular. Course(); } public Freshman. Seminar get. Freshman. Seminar() { return new AFreshman. Seminar(); } public String get. Title() { return title. To. Course. Mapper. get. Title(); }. . . }
Inheritance vs. Delegation: Callbacks declares Reused Class Reusing Class declares Reused method m Abstract or Overridden Method n this. n() Method n Reused method m delegator. n() Method n with possibly more access
Calls vs. Callbacks • Calls – calls from reusing class to reused class • Callbacks – calls from reused class to reusing class. – not to implement a symbiotic relationship – done to service calls
Inheritance vs. Delegation: Constructors/Init methods for callbacks Reused Class declares Constructor/init (…) Reusing Class Reused Class Reusing Class declares Constructor/init (delegator, …)
Access problems • Occur with callbacks. • And if reusing class accesses variables of reused class
Inheriting String Database package collections; public class AString. Database extends AString. History implements String. Database { public void delete. Element (String element) { shift. Up(index. Of(element)); } public int index. Of (String element) { int index = 0; while ((index < size) && !element. equals(contents[index])) index++; return index; } void shift. Up (int start. Index) { int index = start. Index ; while (index + 1 < size) { contents[index] = contents[index + 1]; index++; } size--; } public boolean member(String element) { return index. Of (element) < size; } public void clear() { size = 0; }
Delegating String Set Class as type package collections; import enums. String. Enumeration; and accessing public class ADelegating. String. Database implements String. Database { non public AString. History string. History = new AString. History(); public void delete. Element (String element) { variables in shift. Up(index. Of(element)); same package } public int index. Of (String element) { int index = 0; while ((index < string. History. size) && Instantiating !element. equals(string. History. contents[index])) delegate rather than index++; return index; getting reference } from constructor. init void shift. Up (int start. Index) { int index = start. Index ; method while (index + 1 < string. History. size) { string. History. contents[index] = string. History. contents[index + 1]; index++; } string. History. size--; }
Delegating String Set public boolean member(String element) { return index. Of (element) < string. History. size; } public void clear() { string. History. size = 0; } public int size() { return string. History. size(); } public String element. At (int index) { return string. History. element. At(index); } public String. Enumeration elements() { return string. History. elements(); } public void add. Element(String element) { string. History. add. Element(element); } } Large number of forwarding stubs
Access issues • Callbacks methods – must be given public access if interface types the delegator. – can be given protected or default access – but requires class types, delegator and delegator class in same package • May need to give access to reused class variables also – through public methods – or putting delegate and delegator in same package, giving them protected/default access and using class as type
Cons of Delegation • Need to instantiate multiple classes. • Need to compose instances. • Need to define stub methods • Access problems
Pros of Delegation Reused Class Reused Interface Reusing Class Reusing Interface
Substituting Reused Class 2 Reused Interface Reusing Class 2 Reusing Interface Reused Class 2 Reused Interface Reusing Class Reusing Interface
Substituting Reused Class • Another implementation of reused interface – in inheritance requires another implementation of reusing class that duplicates methods of original reusing class. – In delegation simply requires a different object to be passed to constructor
New Inheriting Proxy Class package models; import assertions. An. Asserter; public class AChecked. Counter 2 extends ACounter 2 { public void add (int amount) { int old. Counter = counter; super. add(amount); An. Asserter. assert(counter == old. Counter + amount, "New counter: " + counter + " != old counter: " + old. Counter + " + amount: " + amount); } }
Orginal Delegating Proxy package models; import assertions. An. Asserter; public class ADelegating. Checked. Counter implements Counter { Counter counter; public ADelegating. Checked. Counter (Counter the. Counter) { counter = the. Counter; } public void add (int amount) { int old. Val = counter. get. Value(); counter. add(amount); int new. Val = counter. get. Value(); An. Asserter. assert(new. Val == old. Val + amount, "New counter: " + new. Val + " != old counter: " + old. Val + " + amount: " + amount); } public int get. Value() { return counter. get. Value(); } }
Multiple Reusing Classes • Inheritance Reused Class Reusing Class 1 Reusing Class 2 – each possible combination of reusing classes bound at compile time – Duplicates code • Delegation – can be changed dynamically
Delegation-based MVC AChecked. Counter ACounter. Console View ACounter. Controller ACounter. JOption View AConsole. Controller. And. View. And. JOption. View
Inheritance-based MVC ACounter. With. Console. View ACounter. With. Console. And. JOption. View. And. Controller No facades or notification needed
Controller with Console View package views; import models. ACounter; public class ACounter. With. Console. View extends ACounter { void append. To. Console(int counter. Value) { System. out. println("Counter: " + counter. Value); } public void add (int amount) { super. add(amount); append. To. Console(get. Value()); } }
Controller with Console and JOption View package views; import models. ACounter; import javax. swing. JOption. Pane; public class ACounter. With. Console. And. JOption. View extends ACounter. With. Console. View { void display. Message(int counter. Value) { JOption. Pane. show. Message. Dialog(null, "Counter: " + counter. Value); } public void add (int amount) { super. add(amount); display. Message(get. Value()); } }
Controller with Console and JOption View and Controller package controllers; import views. ACounter. With. Console. And. JOption. View; import java. io. IOException; public class ACounter. With. Console. And. JOption. View. And. Controller extends ACounter. With. Console. And. JOption. View implements Counter. With. Console. View. And. Controller { public void process. Input() { while (true) { int next. Input = Console. read. Int(); if (next. Input == 0) return; add(next. Input); } } }
Alternative: Delegation-based Configuration An. Observable Counter ACounter. Console View ACounter. Controller AConsole. Controller. And. View ACounter. JOption View
Alternative: Inheritance-based MVC ACounter. With. Console. View. And. Controller New class
Controller with Console and View and Controller package controllers; import views. ACounter. With. Console. And. JOption. View; import java. io. IOException; public class ACounter. With. Console. View. And. Controller extends ACounter. With. Console. View implements Counter. With. Console. View. And. Controller { public void process. Input() { while (true) { int next. Input = Console. read. Int(); if (next. Input == 0) return; add(next. Input); } Only difference between } it and previous inheriting } controller
Inheritance vs. Delegation: Distribution Data and methods of both classes at one location Reused Class Reusing Class instance Reused Class instance Reusing Class instance Can be in two different locations (client/server)
Reusing multiple classes Reused Class 1 Reused Class 2 Reusing Class Reused Class 1 Reusing Class • In Java reusing multiple classes through inheritance not an option. • Can always have multiple instance variables
Pros and Cons of Delegation • Can change reused class without changing reusing class. • Multiple reusing classes can share reused class variables simultaneously. • Variables and methods of reusing and reused class can be on separate computers. • Works in single inheritance languages • Need to instantiate multiple classes. • Need to compose instances. • Need to define stub methods • Access problems Need to weigh pros and cons When benefits of delegation don’t apply use inheritance That is why inheritance exists.
Inheritance is a bad idea • If reusing class has “with” in its name: – ACounter. With. Console. View • If more than one way to do inheritance – Controller can be subclass of view – Or vice versa • If some of the inherited methods are not used: – AString. History extends Vector • Adds methods to add and access string elements rather than object elements • add. String(), string. At() – does not use remove. Element() etc • If reusing class should not be used wherever shared class is used – even if all methods are reused.
Inheritance is a bad idea public ACartesian. Point implements Point { int x, y; public APoint(int the. X, int the. Y) { x = the. X; y = the. Y; } public int get. X() { return x } public int get. Y() { return y } public double get. Radius() { return Math. sqrt(x*x + y*y); }. public double get. Angle() { return Math. atan(y/x); } } public ASquare implements Square { Point center; int side. Length; public ASquare( Point the. Center, int the. Side. Length) { center = the. Center; side. Length = the. Side. Length; } public int get. X() {return center. get. X(); } public int get. Y() {return center. get. Y(); } public int get. Radius() {return center. get. Radius(); } public int get. Angle() {return center. get. Angle(); } public int get. Side. Length() {return side. Length; } } public ASquare extends ACartesian. Point implements Square { int side. Length; public ASquare (int the. X, int the. Y, int the. Side. Length) { x = the. X; y = the. Y; side. Length = the. Side. Length} public int get. Side. Length() {return side. Length}; } ASquare IS-NOTA ACartesian. Point!
Inheritance vs. Delegation in Popular Software: Toolkits Widget Class declares Action Performed super call Widget User Widget Class declares Action Performed delegate call Widget User declares Java 1. 0 Later versions Action Performed
Inheritance vs. Delegation in Popular Software • Main problem with inheritance based widgets – Widget users could not be subclass of any other class because of multiple inheritance • Multiple objects can receive events from same widget. • Widget implementation can be switched • Observer concept supports both approaches – Inherited Observer class vs. Delegated Property. Change. Support • Threads support both approaches – Inheritable Thread class vs. Implemented Runnable Interface
The Importance of Being Earnest public class ABank. Account implements Bank. Account { int current. Balance = 0; public static final int MIN_BALANCE = 100; public ABank. Account (int initial. Balance) { current. Balance = initial. Balance; } public void deposit (int amount) { current. Balance += amount; } public boolean withdraw (int amount) { int min. Necessary. Balance = MIN_BALANCE + amount; if (min. Necessary. Balance <= current. Balance) { current. Balance -= amount; return true; } else return false; } public int get. Current. Balance () { return current. Balance; } public boolean safe. Withdraw (int amount) { An. Asserter. assert(amount > 0, "amount < 0"); boolean ret. Val = withdraw(amount); An. Asserter. assert(current. Balance >= MIN_BALANCE, "current. Balance < MIN_BALANCE"); return ret. Val;
Usage
Usage
Usage Integer. MAX_INT
Usage
Usage
Safe Usage
Integer Overflow and Security • Google for “integer overflow security”
- Prasun dewan
- Prasun dewan
- ( 0 0 299 587 114 ) | ( 0 0 299 587 )
- Nothing but my genius
- Pricechar
- Exec sql begin declare section
- I have nothing to declare but my genius
- Strings in c
- Exec sql begin declare section
- Declare an array alpha of 15 elements of type int
- Mips declare array
- Declare plsql
- Declare deptrec is record
- What did the vietminh declare as its goal
- Declare a two dimensional array of strings named chessboard
- What did the vietminh declare as its main goal?
- Information processing objectives cavr
- Triggers and assertions
- Substantive analytical procedures
- Sample internal audit engagement plan
- General audit procedures
- Psl assertions examples
- Sql assertions
- Audit assertions
- Management assertions definition
- What are the 7 audit assertions
- Audit assertions
- Hkr 112 uitm
- Crm 114 discriminator
- Aiaa s-114
- Csit 114
- Taskj-114
- Solicitud de licencia articulo 114 y 115 decreto 688/93
- Npi torino
- Oesd 114
- Sas114
- Who wrote psalm 114
- Składa się z 114 sur
- Fact act
- Via lucis estaciones imagenes
- Po odparowaniu wody ze 114 g roztworu nasyconego
- Eosc 111
- Decreto 114/2011
- Ppt114
- Some may trust in horses
- What is contact force
- Sometimes you win some sometimes you lose some
- Fire and ice diamante poem
- They say it only takes a little faith to move a mountain
- Some say the world will end in fire some say in ice
- Ice cream countable
- Maksud plagiat kamus dewan
- Pada dewan ambalan ketuanya disebut
- Majlis perbandaran seberang jaya
- Perbedaan dewan pendidikan dan komite sekolah
- Tugas dewan sekolah
- Dewan perwakilan rakyat republik indonesia
- Dewan tanvir ahmed
- Ppdk pramuka
- Doa masuk dewan peperiksaan
- The tiger king character sketch
- Sistem pentadbiran negara ptm
- Maksud fitrah dari segi bahasa dan istilah
- Dewan kehormatan pusat ikatan notaris indonesia
- Dewan jps perlis
- Pembaharuan kerajaan abbasiyah dalam bidang ketenteraan
- Rumah selangorku jenis e
- Cse buet
- Athens sejarah tingkatan 1
- Dewan bahasa dan pustaka cawangan sarawak
- Kata penguat bebas
- Hukum go- food dewan fatwa al- irsyad
- Dewan tanvir ahmed
- Dewan taklimat serdang
- Perwujudan dalam kamus dewan
- Definisi kecederaan sukan
- Dewan satuan pandu berfungsi untuk
- Selambut
- Karakteristik dewan pengawas blu
- Isi aaoifi dan psak syariah
- Minterm
- Comp 252
- Comp 541
- Comp 553
- Comp 523 unc
- Dairy comp 305 tutorial
- Vector 4211
- Comp 211
- Comp 755
- Comp 4620
- Xiao team comp
- Comp 382
- Comp.os.minix
- Comp 335
- Comp 112
- Comp 755
- General machine structure in system programming
- Doterra income disclosure
- Soren comp
- Comp 2121
- Comp sci 301 uw madison
- Comp 5331
- Common case fast
- Comp 411
- User requirements software engineering
- Comp 103
- Comp 482
- Comp
- Comp 345
- Comp 311 textbook notes
- Comp 3000
- Comp 301
- Comp sci 1102
- Comp 401
- Comp4332
- Comp 482
- Comp 249
- Hotel comp set
- Comp 561
- Robozzle solution
- Comp 482
- Hebburn comprehensive school uniform
- Comp 248 midterm
- Comp sci 1027
- Comp 550
- Ubio quality life
- Unc comp 541
- Comp
- Comp 345
- Ubi comp
- Comp 211
- Comp 206
- Comp 512
- Comp 512
- Istituto comprensivo aldo moro sutri
- Comp3000
- Comp3311
- Domain requirements
- Root word opt
- Kidbiz 300
- Comp 350
- Comp 361
- Comp 354
- Comp tox
- Comp4900
- Comp541
- Comp 5331
- Be-comp diagram
- Comp 206