RTTI and Reflection OOD Course Overview l Static

  • Slides: 44
Download presentation
RTTI and Reflection OOD Course

RTTI and Reflection OOD Course

Overview l Static typing Run-Time Type Information in C++ Reflection in Java Dynamic Proxies

Overview l Static typing Run-Time Type Information in C++ Reflection in Java Dynamic Proxies in Java l Syntax, uses and misuses for each l l l 07 December 2020 Object Oriented Design Course 2

Typing l Static Typing, or Strong Typing: • The type of every object and

Typing l Static Typing, or Strong Typing: • The type of every object and expression must be • specified and checked at compile-time Or: All type violations are caught at compile-time l Dynamic Typing or Weak Typing: l What is a type violation? • Type violations are only detected at run-time • Given C x; x. foo(arg); C has no method/operator foo • Or, arg is not an acceptable argument for it 07 December 2020 Object Oriented Design Course 3

Advantages of Static Typing l Reliability Relative cost of error correction, from Boehm, “Software

Advantages of Static Typing l Reliability Relative cost of error correction, from Boehm, “Software Engineering Economics”, 1981: 07 December 2020 Object Oriented Design Course 4

Advantages II l Readability l Efficiency l • Part of an interface, like Design

Advantages II l Readability l Efficiency l • Part of an interface, like Design by Contract • Constant-time dynamic binding • Static binding and inlining • Optimized machine-code instructions Static Typing ≠ Static Binding • Object-oriented language usually use static typing with dynamic binding 07 December 2020 Object Oriented Design Course 5

Run-Time Type Information

Run-Time Type Information

Run-Time Type Information l l l A mechanism for safely bypassing typing Controversial: can

Run-Time Type Information l l l A mechanism for safely bypassing typing Controversial: can be easily abused Capabilities (C++): • Testing if an object is of a given type • Testing if two objects are of the same type • Retrieving the name of a type • Imposing a full order on types C++: dynamic_cast and typeid operators Java: casting and instanceof operator 07 December 2020 Object Oriented Design Course 7

Polymorphic Collections l l l A list<Shape*> is polymorphic How to count rectangles, or

Polymorphic Collections l l l A list<Shape*> is polymorphic How to count rectangles, or find max radius? The language requires a mechanism to test whether a given object is of a given type 07 December 2020 Object Oriented Design Course 8

Polymorphic Collections II double max_radius = 0. 0; for (iterator<Shape*> it = list->begin(); it

Polymorphic Collections II double max_radius = 0. 0; for (iterator<Shape*> it = list->begin(); it != list->end(); it++) if (Circle* c = dynamic_cast<Circle*>(*it)) max_radius = max(max_radius, c->radius()); l l In Java: combine instanceof and C-style cast Cast will succeed for descendants of Circle • Obeys Liskov Substitution Principle 07 December 2020 Object Oriented Design Course 9

dynamic_cast l l Source type must be polymorphic • But not the target type

dynamic_cast l l Source type must be polymorphic • But not the target type • Dynamic casts aren’t useful for static types This enables an efficient implementation: Hold a pointer to type_info in the v-table • my_circle: vptr addresses to the virtual functions for classes and pointers to the functions from each of the objects of the derived class. Whenever there is a function call made to the c++ virtual function, the v-table is used to resolve to the function address. This is how the Dynamic binding happens during a virtual function call. vtable: type_info: “Circle” (bases) type_info: “Shape”

dynamic_cast II l Can be used for pointers and references l In Java l

dynamic_cast II l Can be used for pointers and references l In Java l What about static_cast? • If cast to a pointer failed, return 0 • If cast to a reference failed, throw bad_cast • The instanceof always returns a boolean • All casts are dynamic (checked): Class. Cast. Exception • Equivalent to deprecated C-style casts: (Circle*)s • More efficient: doesn’t examine source object • Required to cast from void* • Best avoided – dynamic_cast is safer 07 December 2020 Object Oriented Design Course 11

dynamic_cast III l Fails if the source object has more than one unique target

dynamic_cast III l Fails if the source object has more than one unique target base class Virtual inheritance: each D has one A 07 December 2020 Ordinary inheritance: each D has two A’s Object Oriented Design Course 12

The typeid operator Returns the type_info* of an object type_info supports comparison l l

The typeid operator Returns the type_info* of an object type_info supports comparison l l Several type_info* may exist in memory for • the same type – required for DLLs Compare its objects, not pointers to objects • type_info has a before() order function Unrelated to inheritance relationships • type_info has a char* name() function Useful for printing debug messages • Useful for keying more per-type data • 07 December 2020 Object Oriented Design Course l l 13

More Uses for RTTI l Receiving an object of uncertain content Object o =

More Uses for RTTI l Receiving an object of uncertain content Object o = my. Object. Stream. read. Object(); if (o instanceof Circle) c = (Circle)o; l Inability to alter ancestor classes • Let Lineman, Boss, Big. Boss inherit Worker • Everyone gets a bonus except the Lineman • Best solution: virtual bonus() in Worker • If Worker can’t be changed (no source, many dependencies) – RTTI is the only solution 07 December 2020 Object Oriented Design Course 14

Misuses of RTTI l It’s easy to use RTTI to violate basics • Single

Misuses of RTTI l It’s easy to use RTTI to violate basics • Single Choice Principle • Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list • Open-Closed Principle • l software entities (classes, modules, functions, etc. ) should be open for extension, but closed for modification Virtual functions are required instead of: void rotate(Shape* s) { if (typeid(s) == typeid(Circle)) // rotate circle algorithm else if (typeid(s) == typeid(Rectangle)) // rotate rectangle algorithm else … 07 December 2020 Object Oriented Design Course 15

Misuses of RTTI II Using over-generic base classes l class List { void put(Object

Misuses of RTTI II Using over-generic base classes l class List { void put(Object o) { … } Object get(int index) { … } Instead of: list<Shape*> This poses several problems Forces casting in source code • Less efficient • Reduces compiler type-checking l • This is why Java will have generics 07 December 2020 Object Oriented Design Course l 16

Misuses of RTTI III l Casting instead of using adapters interface Storable { int

Misuses of RTTI III l Casting instead of using adapters interface Storable { int object. Id(); } interface Book { String get. Name() { … } String get. Author() { … } } class Book. Impl implements Book, Storable { … } l l l “Clients should only work with interfaces” • Only some clients should know about object. Id() Accessing object. Id() requires casting Violates Liskov Substitution Principle 07 December 2020 Object Oriented Design Course 17

RTTI & Casting Guidelines l There are very few correct uses l Usually, casting

RTTI & Casting Guidelines l There are very few correct uses l Usually, casting means a design error l Static typing also tests your design • Polymorphic collections • Validation of an received object • Compromise, when a class can’t be changed • Excluding casting between primitive types • Excluding the current Java collections 07 December 2020 Object Oriented Design Course 18

Reflection

Reflection

What is Reflection? l Library and runtime support for: • Creating class instances and

What is Reflection? l Library and runtime support for: • Creating class instances and arrays • Access and modify fields of objects, classes and elements of arrays • Invoke methods on objects and classes l Java is the most widely used example l All under the Java security model • The java. lang. reflect package • In java. lang: classes Class and Object 07 December 2020 Object Oriented Design Course 20

Reflection API – Class l class Object has a get. Class() method: System. out.

Reflection API – Class l class Object has a get. Class() method: System. out. println(obj. get. Class(). get. Name()); l class Class provides: static Class for. Name(String class. Name); Class[] get. Classes(); // all inner classes Class[] get. Declared. Classes(); // excludes inherited Class. Loader get. Class. Loader(); Constructor get. Constructor(Class[] parameters); Constructor[] get. Constructors(); Constructor[] get. Declared. Constructors(); 07 December 2020 Object Oriented Design Course 21

Reflection API – Class II l class Class also provides: Field get. Field(String name);

Reflection API – Class II l class Class also provides: Field get. Field(String name); // and ‘declared’ version Field[] get. Fields(); // and ‘declared’ version Class get. Declaring. Class(); // for inner classes Class[] get. Interfaces(); Method get. Method(String name, Class[] params); Method[] get. Methods(); // and ‘declared’ version String get. Name(); String get. Package(); int get. Modifiers(); 07 December 2020 Object Oriented Design Course 22

Reflection API – Class III l class Class even provides: Class get. Super. Class();

Reflection API – Class III l class Class even provides: Class get. Super. Class(); boolean is. Array(); boolean is. Assignable. From(Class c); boolean is. Instance(Class c); boolean is. Interface(); boolean is. Primitive(); Object[] get. Signers(); // and other security data String to. String(); Object new. Instance(); // uses default constructor 07 December 2020 Object Oriented Design Course 23

Reflection API - Members 07 December 2020 Object Oriented Design Course 24

Reflection API - Members 07 December 2020 Object Oriented Design Course 24

Reflection API – Members II 07 December 2020 Object Oriented Design Course 25

Reflection API – Members II 07 December 2020 Object Oriented Design Course 25

Reflection API - Others l class Array l class Modifier l class Reflect. Permission

Reflection API - Others l class Array l class Modifier l class Reflect. Permission l Several exception types (ignored here) • Getters and setters by index, get. Length() • new. Instance() of single- or multi-dimensional • Check return values of get. Modifiers() • Beyond normal access/modify/create checks • Currently only supports Suppress. Access. Checks 07 December 2020 Object Oriented Design Course 26

What is it good for? l Development Tools l Runtime services l Frameworks •

What is it good for? l Development Tools l Runtime services l Frameworks • Inspectors of Java. Beans • Debuggers, class browsers • Object Serialization • Object-relational database mapping • Hooks through a class naming convention • Plug-ins and add-ins 07 December 2020 Object Oriented Design Course 27

Object Inspection l l Printing an object fields’ names and values Field[] fa =

Object Inspection l l Printing an object fields’ names and values Field[] fa = obj. get. Class(). get. Fields(); for (int i=0; i < fa. length; i++) print(fa[i]. get. Name(); fa[i]. get(obj). to. String()); Changing a field’s value given its name obj. get. Class(). get. Field(the. Field. Name). set(obj, new. Value); l Printing an inheritance tree, given a class name Class c = Class. for. Name(the. Class. Name); while (c != null) { System. out. println(c. get. Name()); c = c. get. Super. Class(); } 07 December 2020 Object Oriented Design Course 28

Serialization l Writing an object to XML: Class c = obj. get. Class(); String.

Serialization l Writing an object to XML: Class c = obj. get. Class(); String. Buffer output = new String. Buffer(); output. append(“<“ + c. get. Name() + “>”); Field[] fa = c. get. Fields(); for (int i=0; i < fa. length; i++) { output. append(“<“+fa[i]. get. Name()+”>”); output. append(fa[i]. get(obj). to. String()); output. append(“</“+fa[i]. get. Name()+”>”); } 07 December 2020 Object Oriented Design Course 29

Serialization II l Non-primitive reference objects must be recursively written as XML elements •

Serialization II l Non-primitive reference objects must be recursively written as XML elements • Use Class. is. Primitive() to test each field type l Fields marked as transient aren’t written l Objects must be rebuilt from XML data • Use Modifier. is. Transient(Field. get. Modifiers()) • Use Class. for. Name() to find object’s class, Class. get. Field() to find fields, and Field. set() l Java serialization is implemented this way • But writes to a more efficient binary format 07 December 2020 Object Oriented Design Course 30

Plug-Ins l Your new game enables downloading new weapons from the web Define an

Plug-Ins l Your new game enables downloading new weapons from the web Define an interface for Weapon Download *. class files of new stuff into: l When the program starts: l l • A directory called c: My. Gameweapons (or weapons. jar) • where c: My. Game is the home class path String[] files = find. File. Names(plugin. Dir + “*. class”); Weapon[] weapons = new Weapon[files. length]; for (int i=0; i < weapons. length; i++) weapons [i] = (Weapon)Class. for. Name( “weapons. ”+files[i]). new. Instance(); 07 December 2020 Object Oriented Design Course 31

Plug-Ins II l The weapons array is a list of prototypes l Multiple interfaces

Plug-Ins II l The weapons array is a list of prototypes l Multiple interfaces are easy to support l All Weapon code is type-safe l There are better plug-in implementations • Alternative: Hold Class[] array • Use Class. get. Interfaces() on downloaded files • And secure, if there’s a security policy • See class Class. Loader • Classes can be stored and used from the net 07 December 2020 Object Oriented Design Course 32

Reflection Guidelines l l l Reflection is a new reuse mechanism It’s a very

Reflection Guidelines l l l Reflection is a new reuse mechanism It’s a very expensive one Use it when field and class names as strings were necessary anyway • Class browsers and debuggers, serialization to files or databases, plug-in class names l Use it to write very generic frameworks l Don’t use it just to show off… • Plug-ins and hooks to be written by others 07 December 2020 Object Oriented Design Course 33

Dynamic Proxies

Dynamic Proxies

Dynamic Proxies l Support for creating classes at runtime • Each such class implements

Dynamic Proxies l Support for creating classes at runtime • Each such class implements interface(s) • Every method call to the class will be delegated to a handler, using reflection • The created class is a proxy for its handler l Applications • Aspect-Oriented Programming: standard error handling, log & debug for all objects • Creating dynamic event handlers 07 December 2020 Object Oriented Design Course 35

Invocation Handlers l Start by defining the handler: • interface java. lang. reflect. Invocation.

Invocation Handlers l Start by defining the handler: • interface java. lang. reflect. Invocation. Handler • With a single method: Object invoke( Object proxy, Method method, Object[] args) l // return value of call // call’s target // the method called // method’s arguments The “real” call made: proxy. method(args) • Simplest invoke(): method. invoke(proxy, args) 07 December 2020 Object Oriented Design Course 36

Creating a Proxy Class l Define the proxy interface: interface Foo { Object bar(Object

Creating a Proxy Class l Define the proxy interface: interface Foo { Object bar(Object obj); } l Use java. lang. reflect. Proxy static methods to create the proxy class: Class proxy. Class = Proxy. get. Proxy. Class( Foo. class. get. Class. Loader(), new Class[] { Foo. class }); l l l First argument – the new class’s class loader 2 nd argument – list of implemented interfaces The expression C. class for a class C is the static version of C_obj. get. Class() 07 December 2020 Object Oriented Design Course 37

Creating a Proxy Instance l l A proxy class has one constructor which takes

Creating a Proxy Instance l l A proxy class has one constructor which takes one argument – the invocation handler Given a proxy class, find and invoke this constructor: Foo foo = (Foo)proxy. Class. get. Constructor(new Class[] { Invocation. Handler. class }). new. Instance(new Object[] { new My. Invocation. Handler() }); l Class Proxy provides a shortcut: Foo f = (Foo) Proxy. new. Proxy. Instance( Foo. class. get. Class. Loader(), new Class[] { Foo. class }, new My. Invocation. Handler()); 07 December 2020 Object Oriented Design Course 38

A Few More Details l We ignored a bunch of exceptions l A proxy

A Few More Details l We ignored a bunch of exceptions l A proxy class’s name is undefined l l • Illegal. Argument. Exception if proxy class can’t exist • Undeclared. Throwable. Exception if the handler throws an exception the interface didn’t declare • Class. Cast. Exception if return value type is wrong • Invocation. Target. Exception wraps checked exceptions • But begins with Proxy$ Primitive types are wrapped by Integer, Boolean, and so on for argument and return values The syntax is very unreadable! • Right, but it can be encapsulated inside the handler 07 December 2020 Object Oriented Design Course 39

A Debugging Example l l l We’ll write an extremely generic class, that can

A Debugging Example l l l We’ll write an extremely generic class, that can wrap any object and print a debug message before and after every method call to it Instead of a public constructor, it will have a static factory method to encapsulate the proxy instance creation It will use Invocation. Target. Exception to be exception-neutral to the debugged object 07 December 2020 Object Oriented Design Course 40

A Debugging Example II l The class’s definition and construction: public class Debug. Proxy

A Debugging Example II l The class’s definition and construction: public class Debug. Proxy implements java. lang. reflect. Invocation. Handler { private Object obj; public static Object new. Instance(Object obj) { return java. lang. reflect. Proxy. new. Proxy. Instance( obj. get. Class(). get. Class. Loader(), obj. get. Class(). get. Interfaces(), new Debug. Proxy(obj)); } private Debug. Proxy(Object obj) { this. obj = obj; } 07 December 2020 Object Oriented Design Course 41

A Debugging Example III l The invoke() method: public Object invoke(Object proxy, Method m,

A Debugging Example III l The invoke() method: public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { Object result; try { System. out. println("before method " + m. get. Name()); result = m. invoke(obj, args); } catch (Invocation. Target. Exception e) { throw e. get. Target. Exception(); } catch (Exception e) { throw new Runtime. Exception("unexpected: ” + e. get. Message()); } finally { System. out. println("after method " + m. get. Name()); } return result; } 07 December 2020 Object Oriented Design Course 42

A Debugging Example IV l Now that the handler is written, it’s very simple

A Debugging Example IV l Now that the handler is written, it’s very simple to use. Just define an interface: interface Foo { Object bar(Object o); } class Foo. Impl implements Foo { … } l And wrap it with a Debug. Proxy: Foo foo = (Foo)Debug. Proxy. new. Instance(new Foo. Impl()); l l This is not much different than using any proxy or decorator Just much, much slower 07 December 2020 Object Oriented Design Course 43

Dynamic Proxies: Summary l Applications similar to above example: l Other kinds of applications

Dynamic Proxies: Summary l Applications similar to above example: l Other kinds of applications exist as well • Log every exception to a file and rethrow it • Apply an additional security policy • Dynamic event listeners in Swing • In general, being an observer to many different objects or interfaces at once l It’s a very new feature – from JDK 1. 3 • There may be other future applications 07 December 2020 Object Oriented Design Course 44