Præsentation er lastning. Vent venligst

Præsentation er lastning. Vent venligst

VOOP, 8 april 20021 Refleksion i objekt orienterede programmeringssprog Mandag 8/4 2002 Kasper Østerbye.

Lignende præsentationer


Præsentationer af emnet: "VOOP, 8 april 20021 Refleksion i objekt orienterede programmeringssprog Mandag 8/4 2002 Kasper Østerbye."— Præsentationens transcript:

1 VOOP, 8 april 20021 Refleksion i objekt orienterede programmeringssprog Mandag 8/4 2002 Kasper Østerbye

2 VOOP, 8 april 20022 Mål med denne lektion At give en fornemmelse for hvad refleksion er i programmeringssprog At give en motivation for dets eksistens At give en fornemmelse for hvad man kan gøre med det

3 VOOP, 8 april 20023 Modellering Car color length maxSpeed start() turn(angle) crash() Modellering toString() Hvis man skal opretholde ideen om at objekter modellerer udvalgte aspekter af den virkelighed et system skal repræsentere, så duer det ikke med metoder og andre egenskaber ved objekterne som repræsenterer egenskaber der er knyttet til det at objektet er en entitet i en computer.

4 VOOP, 8 april 20024 Class name superclass fields methods new() toString(obj) Modellering 2 Car color length maxSpeed start() turn(angle) crash() Modellering Ideen er at man laver en model af klasserne. Denne model modellerer så de egenskaber som klasserne har. Modellering Ud fra et symmetri synspunkt, skal der så være en model af modelen’s model osv. Dette gøres ofte ved en ”sløjfe”

5 VOOP, 8 april 20025 Meta klasser Klassen for en klasse kaldes en Metaklasse. Fordi klasserne er modellerede, og dermed tilstede som objekter på køretidspunktet, indeholder programmet ikke blot en model af en udvalgt del af virkeligheden, men også en model af sig selv. Det er denne selv modellering, der giver anledning til betegnelsen refleksion. Forskellige programmeringssprog håndterer dette forskelligt –Klasser er ikke modelleret i sproget. (F.eks. C++) –Klasser er modelleret i sproget, men kan ikke ændres på køretid. (F.eks. Java) –Klasser er modelleret i sproget, og kan ændres på compile tid, men ikke Køretid (F.eks. OpenJava). –Klasser er modelleret, og kan ændres på køretid (F.eks. Smalltalk & CLOS). og nogle prototype implementationer af Java.

6 VOOP, 8 april 20026 Java Java er godt med: Når man erklærer en metode eller attribut static i Java, så svarer det til at man erklærer den i meta klassen. Der er en klasse der hedder Class i java. Klasser i Java er instanser af Class. Man kan så undersøge hvilke metoder en klasse har vha. dens klasse objekt. Man kan sætte metode kald op så man kan kalde en metode hvis navn man kender i en string. Java er noget skammel Java har kun introspektion (man kan kun aflæse, ikke ændre) Java har ikke konstruktører for klasse objekter. Man kan ikke lave subklasser af Class. Java har en indbygget ”new” operation. Altså Car c = new Car(); egentlig burde dette være Car c = Car.new();

7 VOOP, 8 april 20027 Hvad bruger man reflektion til normalt At finde ud af hvilke metoder en klasse har på kørselstidspunkt. –Hvordan virker JUnit? –Hvordan virker en objekt-browser –Debuggere Dynamisk loadning og indkorporering af klasser i et system Enterprise beans forbindelse til database Generel serialisering og unserialisering Debuggere hvor man kan aktivere metoder på objekter Omdefinere hvordan metodekald virker, så man har automatisk distribution for nogle klasser. Skjult persistens. Et objekt læses først op på det tidspunkt man har brug for det. Sprog tilpasning

8 VOOP, 8 april 20028 Eksempel - JUnit JUnit aftesteren gør: 1.tager et klasse navn som input, 2.kalder setUp metoden 3.kalder alle metoder der starter med ”test” 4.rapporterer om test metoder der gav vejl. Det skal være muligt at få fat i en klasse ud fra dens navn som String Det skal være muligt at finde alle metoder i en klasse Det skal være muligt at finde metodernes navne Man skal kunne kalde en metode hvis navn man kun kender som en String

9 VOOP, 8 april 20029 Skaffe en klasse ud fra dens String navn Class myClass = Class.forName(className); Object obj = myClass.newInstance(); public class UnitTester { private Class testClass; private Vector testMethods; private TestCase testObject; public void setClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { testClass = null; testClass = Class.forName(className); testObject =(TestCase) testClass.newInstance(); }

10 VOOP, 8 april 200210 Find alle metoder i en klasse public void getMethods(){ // get the methods in testClass that takes no arguments, and with // a methodName that starts with "test". testMethods = new Vector(); try{ Method[] all = testClass.getMethods(); for (int i = 0; i<all.length; i++){ if ( all[i].getName().startsWith("test") ){ testMethods.add(all[i]); } }catch(SecurityException ahvaba){ }

11 VOOP, 8 april 200211 Kald en metode ud fra et metode objekt Iterator itr = testMethods.iterator(); while ( itr.hasNext() ){ Method m = (Method)itr.next(); try{ m.invoke(testObject, new Object[0]); result += m.getName() + " OK\n"; } catch... }

12 VOOP, 8 april 200212 En test klasse public class EnTestKlasse extends TestClass { public void setUp(){ System.out.println("setUp is activated"); } public void testA(){// OK assert("7 er størst",7>5); } public void testB(){// Falsk assert ("syv er mindst",7<5); } public void testC(){// Failure assert ("Vi kan ikke dividere med 0", 7/0 == 8); }

13 VOOP, 8 april 200213 Klasse diagram for Java objekt model Class ClassLoader AccessibleObject MethodConstructorField Modifer Array Object Membership Instantiation Inheritance

14 VOOP, 8 april 200214 Design mønstre og programmeringsprog I et programmeringssprog har sprog konstruktionerne A, B og C (F.eks. klasser, arv og metoder) Når man en tid har brugt disse konstruktioner, kan man lave mønstre X, Y over brugen af disse konstruktioner. (F.eks. Singleton, Observer og Command). Når man i en tid har brugt disse mønstre vil nogle af dem blive indbyggede som nye programmeringsprogskonstruktioner, eller blive understøttet af klasse biblioteker. Når man en tid har brugt disse nye programmeringssprogskunstruktioner vil man lave mønstre over deres brug. osv.

15 VOOP, 8 april 200215 Design mønstre og programmeringsprog I dag understøttes Singleton i sprog som Beta: Car : {...}; // klasse som i Java myCar : @Car // final myCar = new Car(); customCar : @{...} // ikke i Java Observer mønsteret understøttes i java.util af interface observer og klassen observable. Abstract factory er delvist understøttet i Smalltalk, idet new Car ikke behøver at lave en ny Car, men kan ændres til at instantiere noget andet (typisk en subklasse eller en proxy).

16 VOOP, 8 april 200216 Design mønstre og programmeringsprog Fordele ved at understøtte design mønstre direkte i programmeringssprog og klassebiblioteker. –Man er i meget højere grad tilbøjelig til at benytte noget som oversætteren kan understøtte, end at man selv skal holde styr på detaljerne. –Det er tydeligere at der er benyttet en klasse eller en sproglig konstruktion, end at der er benyttet et mønster. –Oversætteren kan ofte optimere bedre end vi kan som programmører. –Det kan være meget nemmere at benytte mønstret hvis det er støttet af et bibliotek eller sprogkonstruktion

17 VOOP, 8 april 200217 Command mønstret class SimpleCommand { Object receiver; Method action; SimpleCommand ( Object receiver, String methodName ){ this.receiver = receiver; action = findMethod(methodName); } public void execute() { action.invoke( receiver, new Object[0] ); } private Method findMethod( String methodName ) { // næste slide }

18 VOOP, 8 april 200218 findMethod private Method findMethod( String methodName ) { try{ Class receiversClass = receiver.getClass(); Method action = receiversClass.getMethod(methodName, new Class[0]); return action; } catch (NoSuchMethodException uups) { // Handle mispelling } catch ( SecurityException upps ){ // Handle it } return null; }

19 VOOP, 8 april 200219 Skabelse og kald af SimpleCommand Command cmd; cmd = new SimpleCommand( someObject, ”addCustomer” );... cmd.execute();

20 VOOP, 8 april 200220 Proxy’er Et proxy objekt er et objekt der træder i stedet for et andet. Men Alle metoder ser ud som draw. Der er mange forskellige typer data der har behov for at blive behandlet sådan aDocument image anImageProxy fileName realImage anImage data if (realImage == null) realImage = load(fileName); realImage.draw(...) draw(...)

21 VOOP, 8 april 200221 Java proxy class java.lang.reflect.Proxy klassen tilbyder en mekanisme der kan omforme alle kald til et proxy objekt til et generisk kald af en metode der kaldes invoke. Metoden Proxy.newProxyInstance skaber en ny Proxy ud fra tre argumenter: 1)(En class loader – ikke væsentlig) 2)En række interfaces som proxyen skal opfylde 3)En handler, som har til opgave at opfylde interface fra 2.

22 VOOP, 8 april 200222 ImageProxy IDrawable aDocument image anImageProxy fileName realImage anImage data if (realImage == null) realImage = load(fileName); realImage.draw(...) draw(...)

23 VOOP, 8 april 200223 Proxy interface Drawable { void draw(...); void resize(...); void move(...);... } class Document Drawable[] elements;... elements[3] = Proxy.newProxyInstance ( this.getClass().getClassLoader(), Drawable.class, new ImageHandler(”Image2.jpg”) )... elements[3].draw(); } class ImageHandler implements InvocationHandler { private String fileName; private Image anImage; ImageHandler(String fileName){ this.fileName = fileName; } public Object invoke (Object proxy, Method method, Object[] args) { if ( anImage == null ) anImage = loadImage(fileName); method.invoke(anImage, args); } anImage.draw(...)

24 VOOP, 8 april 200224 En log proxy Alle metoder der bliver kaldt på proxyen vil blive lavet om til et kald af en enkelt metode på handleren. invoke(Object proxy, Method method, Object[] args) Metoden er den metode der blev forsøgt kaldt, og args de argumenter der blev givet med. Proxyen er den proxy der modtog det oprindelige kald.

25 VOOP, 8 april 200225 Logging import java.lang.reflect.*; public class LoggerTest { public static void loggingTest(){ Hus etHus = new Hus(); IHus proxyHus = (IHus)(Proxy.newProxyInstance( etHus.getClass().getClassLoader(), new Class[]{IHus.class}, new Logger(etHus) )); proxyHus.setEjer("Hans Hansen"); proxyHus.setGrund(534); System.out.println("Ejer: " + proxyHus.getEjer() ); }

26 VOOP, 8 april 200226 Logging handler import java.lang.reflect.*; public class Logger implements InvocationHandler { Object theRealThing; Logger(Object obj){ theRealThing = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("I am calling " + method.getName()); try{ return method.invoke(theRealThing, args); } finally { System.out.println("I am returning from " + method.getName() ); }

27 VOOP, 8 april 200227 Brug en factory metode til proxy skabelse Proxy.newProxyInstance ( this.getClass().getClassLoader(), Drawable.class, new ImageHandler(”Image2.jpg”) ) Contra new Image(”Image2.jpg”) Den store forskel mellem disse to påvirker klart hvordan klienten ser ud. Der skal derfor laves en factory metode i Image klassen class Image { public static Image create(String fileName){ // lav enten image eller proxy } I klienten bliver det derefter et kald på formen Image.create(”Image2.jpg”) uanset om der anvendes proxy eller ej.

28 VOOP, 8 april 200228 Design overvejelser Problemer ved brug af refleksion Typecheck forsvinder ofte Effektivitet Læsbarhed Virker magisk på nogle Fordele ved reflektion Der er ting der kun kan gøres på denne måde Læsbarhed Det er ret enkelt

29 VOOP, 8 april 200229 OpenJava De eksempler vi indtil nu har set har været introspektive, dvs. at vi haf aflæst hvordan klasser er bygget op, og vi har kaldt eksisterende metoder. Man kunne også forstille sig at man havde mulighed for at manipulere hvordan klasserne er bygget op. Class myCarClass = Car.class.makeSubClass(); myCarClass.addField(Person.class, ”owner”); myCarClass.addMethod(”start”,Void.TYPE, new Class[0]); og lign.

30 VOOP, 8 april 200230 OpenJava public class Hello instantiates VerboseClass { public static void main( String[] args ) { hello(); } public static void hello() { System.out.println( "Hello, world." );} } public class Hello { public static void main( String[] args ) { System.out.println( "main is called." ); hello(); } public static void hello() { System.out.println( "hello is called." ); System.out.println( "Hello, world." ); } } OpenJava benytter sig af compile-time reflektion, hvilket betyder at man har manipulation på oversættelses tidspunkt, mens man kun har introspektion (som i alm. Java) på oversættelses tidspunkt. Det OpenJava gør er at man kan beskrive hvilken metaklasse en klasse skal være instans af. (Her VerboseClass).

31 VOOP, 8 april 200231 OpenJava Metaklassen beskriver hvordan klasse beskrivelsen skal fortolkes. import openjava.mop.*; import openjava.ptree.*; public class VerboseClass instantiates Metaclass extends OJClass { public void translateDefinition() throws MOPException { OJMethod[] methods = getDeclaredMethods(); for (int i = 0; i < methods.length; ++i) { Statement printStatement = makeStatement( "System.out.println( \"" + methods[i] + " is called.\" );" ); methods[i].getBody().insertElementAt(printStatement, 0 ); }

32 VOOP, 8 april 200232 Og hvad så. I en fejlsøgnings situation er det fikst at kunne sætte udskrifter ind alle steder uden at rette i koden om man så kan sige. I stedet for udskrift kunne man sætte en tæller ind, der kikker på hvor ofte en metode er kørt. –Det kunne f.eks. være relevant i forbindelse med aftestning hvor man kunne ønske at sikre sig at alle metoder var prøvet mindst en gang. Man kunne sætte et stop-ur ind først og sidst i metoder. Det kan bruges i forbindelse med performance.

33 VOOP, 8 april 200233 Et andet eksempel: Monitor Når man i Java laver en delt resource skal man huske at bruge synchronized foran alle public metoder. En sådan brug af en klasse kaldes i inden for concurrent programmering for en Monitor. Når vi modellerer en bankkonto, så skal der netop være beskyttet adgang til den. Altså kunne vi lade public betyde at der både er public og syncronized for en monitor. class Konto instantiates Monitor { private double saldo; public void hæv(double beløb){ saldo = saldo – beløb; } public void indsæt(double beløb){ saldo = saldo + beløb; }

34 VOOP, 8 april 200234 Monitor metaklassen import openjava.mop.*; import openjava.ptree.*; public class Monitor instantiates Metaclass extends OJClass { public void translateDefinition() throws MOPException { OJMethod[] methods = getDeclaredMethods(); for (int i = 0; i < methods.length; ++i) { if (! methods[i].getModifiers().has( public )) continue; // Burde sikre os at den ikke er static methods[i].getModifiers().add(OJModifer.SYNCRONIZED); } // Her skulle vi sikre os at der kun er private felter }

35 VOOP, 8 april 200235 Monitor og modellering Fra et modelleringsperspektiv er det der sker her rigtigt. På samme måde som når vi modellerer en bil ved en generel klasse, beslutter vi os her for at en konto skal modelleres ved en speciel type klasse, nemlig monitor. Det ville være forkert hvis Monitor var superklasse, idet Monitor ikke en et begreb i banker (hvis det er betyder det noget andet).

36 VOOP, 8 april 200236 Java udvidelser med OpenJava Man kan udvide med nye modifiers. class Truck extends Car... {... public overriding void turn(double angle){....} } Man kan udvide med nye sproglige konstruktioner 2 steder, umiddelbart før {...} i metoder og klasser. F.eks. –public void hæv(double beløb) pre (saldo+beløb > 0) { saldo = saldo – beløb} –class Car instantiates ComposedObject part body type Body lifts color {....}

37 VOOP, 8 april 200237 Opsummering Fra et modelleringssynspunkt kan man skille det at lave en model af problem området, for de aspekter der har med modellen at gøre som model. Det at der er en objektmodel for javas klasser (og metoder mv.) gør at man kan skrive nogle meget generelle abstraktioner – ikke problem område abstraktioner, men objekt abstraktioner. Man kan bruge meta programmering til visse former for sprog udvidelser. En sprog udvidelse kan betyde at man kan modellere problem området mere direkte. F.eks. –Roller –Monitor –Associationer Brug det med omtanke, det er et slagkraftigt værktøj, og skal ikke bruges i applikationsudvikling.


Download ppt "VOOP, 8 april 20021 Refleksion i objekt orienterede programmeringssprog Mandag 8/4 2002 Kasper Østerbye."

Lignende præsentationer


Annoncer fra Google