Hos vad? och bör därför vara instanseller klassvariabel i vilken klass?



Relevanta dokument
EnKlass. Instans 3 av EnKlass. Instans 2 av EnKlass

Kort om klasser och objekt En introduktion till GUI-programmering i Java

Objektorienterad programmering i Java

Introduktion till arv

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Sätt att skriva ut binärträd

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

Tentamen OOP

Classes och Interfaces, Objects och References, Initialization

OOP Objekt-orienterad programmering

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

Övningar Dag 2 En första klass

Föreläsning 13 och 14: Binära träd

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

Enkla variabler kontra referensvariabel

Programmering för språkteknologer II, HT2014. Rum

TENTAMEN. Kurs: Objektorienterad programmeringsmetodik 5DV133 Ansvarig lärare: Anders Broberg. VT-13 Datum: Tid: kl

Laboration 1 - Grunderna för OOP i Java

Föreläsning 8 Programmeringsteknik och Matlab DD1312. Klassmetod. Egen modul

Föreläsning 6: Introduktion av listor

Grundläggande programmering med C# 7,5 högskolepoäng

Föreläsning 8 Programmeringsteknik och Matlab 2D1312/2D1305. Klass Object, instans av klass public/private Klassvariabler och klassmetoder

Idag. statiska metoder och variabler. private/public/protected. final, abstrakta klasser, gränssnitt, delegering. wrapper classes

Föreläsning 4: Poster

Mer om klasser och objekt

Administrativt. Programmeringsteknik för I1. Dagens program. Objektorienterad programmering

Objektorienterad programmering

Mer grafik. Jan Erik Moström

Objektsamlingar i Java

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

TDDE10 TDDE11, 725G90/1. Objektorienterad programmering i Java, Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning 5-6 Innehåll

Försättsblad till skriftlig tentamen vid Linköpings Universitet

"Är en"-relation. "Har en"-relation. Arv. Seminarium 2 Relevanta uppgifter. I exemplet Boll från förra föreläsningen gällde

Dagens program. Programmeringsteknik och Matlab. Objektorienterad programmering. Vad är vitsen med att ha både metoder och data i objekten?

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Programmeringsteknik med C och Matlab

Lösningsförslag övning 2.

Tentamen DE12, IMIT12, SYST12, ITEK11 (även öppen för övriga)

TENTAMEN OOP

Föreläsning 13 Innehåll

Objektorienterad programmering D2

Föreläsning 16 Arv. Jan Lönnberg T Grundkurs i programmering

Laboration 3, uppgift En klass för en räknare

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

public och private Obs: private inte skyddar mot access från andra objekt i samma klass.

2203$( Föreläsning ii - Mer om Java bla this och konstruktorer. Exempel: lampa

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 14

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

1 Uppgift 1. a) Skapar ett Company-objekt med hjälp av den överlagrade konstruktorn. Du kan själv välja värden på instansvariablerna.

Föreläsning 9: Arv och UML

Objektorienterad Programkonstruktion, DD1346 FACIT. Tentamen , kl

Idag: Centrerad utskrift. Granskning. DD1311 Programmeringsteknik med PBL. Granskning Felhantering GUI. Föreläsning 15.

Tänk på följande: Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

I STONE. I Variabler, datatyper, typkonvertering. I Logiska och matematiska uttryck. I Metoder-returvärde och parametrar. I Villkorssatser if/else

Föreläsning 3.1: Datastrukturer, en översikt

2D1311 Programmeringsteknik för Bio1 och Bio2, vt 2003 Fiktivt prov På flervalsfrågorna är endast ett svar rätt om inget annat anges i frågan! Det rik

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

OOP Objekt-orienterad programmering

Att bekanta dig med NetBeans programmeringsmiljö och skriva några enkla program med programmeringsspråket Java.

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Objektorienterad Programmering DAT043

DAT043 - Föreläsning 7

Klasshierarkier - repetition

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

TDDE10 TDDE11, 725G90. Objektorienterad programmering i Java, Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Några inbyggda funktioner (med resultat!) Introduktion till programmering D0009E. Föreläsning 4: Villkor och rekursion. Modulus-operatorn.

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Tentamen för kursen Objektorienterad programvaruutveckling GU (DIT010)

Java, klasser, objekt (Skansholm: Kapitel 2)

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design Alex Gerdes, 2016

Modeller, Objekt och Klasser

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Objektorienterad programmering Föreläsning 12. Copyright Mahmud Al Hakim

Typhierarkier del 1 Gränssnitt, ärvning mellan gränssnitt, ärvning mellan klasser

Dagens program. Programmeringsteknik och Matlab. Vad är arv? Vi ärver från GregorianCalendar. Kan vi bygga vidare på existerande klasser?

Kopiering av objekt i Java

Lite modifierad Laboration 1 Körkortsprov för Smalltalk och VisualWorks

1 Funktioner och procedurell abstraktion

Lab5 för prgmedcl04 Grafik

Objekt och referenser

Inkapsling tumregler. Åtkomstmodifikatorer, instantiering, referenser, identitet och ekvivalens, samt klassvariabler. public och private

Datalogi I, grundkurs med Java 10p, 2D4112, Fiktiv tentamen, svar och lösningar och extra kommentarer till vissa uppgifter 1a) Dividera förs

725G61 - Laboration 7 Implementation av ett API. Johan Falkenjack

Överlagring, static, testning, formella metoder och undantag! Förelasning 13!! TDA540 Objektorienterad Programmering!

1 Egna klasser. 1.1 En punkt-klass

TDDE10 TDDE11, 725G90. Objektorienterad programmering i Java, Föreläsning 3 Erik Nilsson, Institutionen för Datavetenskap, LiU

Klasser och objekt, referenser Grundkurs i programmering med Python

Objektorienterad programmering

DAT043 - föreläsning 8

Mer till P-uppgiften: Dokumentation. Nyheter. Algoritm för sökning. Mer hjälp. DD1311 Programmeringsteknik med PBL

Objekt och klasser - Introduktion

UML. Klassdiagr. Abstraktion. Relationer. Överskugg. Överlagr. Aktivitetsdiagram Typomv. Typomv. Klassdiagr. Abstraktion. Relationer.

Transkript:

Övningstillfälle 5 Lite kort repetition om klasser och objekt class EnKlass(KlassAttÄrvaFrån): klassvariabel = 5 def init (self) KlassAttÄrvaFrån. init (self) self.instansvariabel = 10 s = 'klassvariabel= '+str(enklass.klassvariabel) s +=', instansvariabel='+str(self.instansvariabel) Först definitionen av klassens namn och vad den ärver. Vi får alla metoder som finns i superklassen. Sedan kommer vanligen eventuella klassvariabler, som alltså finns en gång i klassen, och alltså är gemensam för alla instanser! Konstruktorn Man bör anropa superklassens init. Sätter en instansvariabel, som alltså kan ha olika värde för varje instans Vi överskuggar str () metoden och returnerar klassvariabelns och instansvariabelns värden i strängform Exempel: "Bil" (typ av fordon), "Mazda 6" (bilmodell), "Pappas Mazda 6" "Bil" är ett allmänbegrepp; det är "Mazda 6" också, men det är ett mer specifikt begrepp. "Pappas Mazda 5" är däremot (en bestämd beskrivning av) ett enskilt ting. 1 Begreppet "Bil" motsvaras i Python (lämpligen) av en klass; "Mazda 6" (modellen) motsvaras av en subklass som ärver av superklassen Bil. "Pappas Mazda 6" är en enskild bil, eller ett enskilt objekt, dvs. (lämpligen) en instans av Mazda6 (och därmed samtidigt en instans av Bil). Egenskap Aktuell mängd bensin Bensintankens kapacitet Plats (Location) Antal dörrar Ägare såvida vi inte menar bilmodellens "ägare" Antal växlar Hos vad? och bör därför vara instanseller klassvariabel i vilken klass? Är en egenskap hos alla enskilda bilar (instanser), men olika bilar av samma modell har inte mängden bensin gemensamt => instansvariabel i Bil Är visserligen en egenskap hos varje enskild bil; men alla bilar av samma modell har samma kapacitet => egenskap hos modellen => klassvariabel i Mazda6 Hos alla enskilda bilar, alltså en instansvariabel i Bil. Alla enskilda bilar har ett visst antal dörrar, men alla bilar av en viss modell har samma antal dörrar, alltså en klassvariabel i Mazda6 Hos alla enskilda bilar och är därmed lämpligen en instansvariabel i Bil Alla Mazda 6 "ägs" av Mazda => egenskap hos modellen => en klassvariabel i Mazda6 Egenskap hos modellen, dvs. klassvariabel i 1 Förhållandet mellan begrepp och de enskilda ting som faller under ett begrepp är ett gammalt filosofiskt problem. Här intresserar vi oss dock för hur detta praktiskt berör klasser respektive objekt.

Mazda6 Antal sittplatser Hos modellen => klassvariabel i Mazda6 Max tillåtet antal passagerare Modellen => klassvariabel i Mazda6 såvida vi inte menar för alla bilar Egenskap hos alla bilar i allmänhet (i Sverige får en bil ha max förare + 8 passagerare) => klassvariabel i Bil Minimikrav som t.ex. krav på belysning, Alla bilar i allmänhet (alla bilar ska uppnå de styrning, speglar, bromsar lagstadgade kraven för bilfordon) => klassvariabler i Bil Kört antal mil (milräknare) Hos alla enskilda bilar => instansvariabel i Bil Registrerings-id (registreringsskylt) Hos alla enskilda bilar => instansvariabel i Bil Modellbeteckningen "Mazda 6" Hos modellen => klassvariabel i Mazda6 Benämningen "Bil" Alla bilar i allmänhet kan benämnas "Bil" => klassvariabel i Bil Kommentar: Det är inte alltid självklart om en egenskap ska vara instans- eller klassvariabel, ej heller i vilken klass den ska finnas. Det beror nämligen på hur man har tänkt sig att klasshierarkin kan kommat att byggas ut. Kan man t.ex. tänka sig Lådbil som en subklass till Bil? Om ja, så blir en hel del av variablerna ovan irrelevanta för den klassen och man kanske får tänka om. Fråga 1: Om du är osäker på om en variabel bör vara en instans- eller klassvariabel, vad bör du välja? (Eller omvänt, vilket val kan leda till störst problem?) 2 Fråga 2: En av fördelarna med klassvariabler är att de tar mindre plats. Antag att du har en list-variabel som innehåller 1000 heltal. Hur mycket minne kommer gå åt om listan är en klassvariabel? Hur mycket går åt om varje instans har en separat (dvs. inte referenser till en och samma lista) lista och antalet instanser är 10.000? 3 class Car: MAX_PASSENGERS = 9 # Inklusive förare TERM = 'Bil' # benämning def init (self, owner, plate): self.owner = owner self.plate = plate self.milage = 0 Definiera klassen Bil Med bl.a. information om tillåtet antal passagerare och benämning (konstanta klassvariabler) Konstruktor 2 Du bör låta den vara en instansvariabel, då detta aldrig kan leda till direkt logiska fel som hindrar programmet från att fungera, dvs. det gör inget (logiskt sett) att vi lagrar en variabel onödigt många gånger genom att lägga den i varje instans. Om variabeln däremot kommer anta olika värden för olika instanser, blir det helt fel om vi hanterar det genom en klassvariabel som är gemensam för alla instanser. 3 Ett heltal tar upp minst två byte. Klassvariabeln upptar då ca 2 kilobyte, medan instansvariablerna tillsammans upptar > 2 kilobyte gånger 10.000 instanser = 20 megabyte (ganska onödigt om vi vet att alla instanser kommer att ha exakt samma lista). 4 En sådan metod kallas abstrakt, och därmed borde klassen också anses vara abstrakt. Typiskt för statiska OOspråk som Java, är att det inte skulle vara möjligt/tillåtet att skapa instanser av en sådan klass, men i Python går det bra, men om metoden anropas, riskerar vi att krascha! Dessutom finns ingen mekanism i Python som verkligen tvingar programmeraren att implementera ofullständiga metoder. Mönstret går igen ganska ofta: Python är ett "slappt" språk, som låter programmeraren slappa, men riskerar därmed att släppa igenom osäkra och dåligt skrivna program. Läs http://code.activestate.com/recipes/266468/ för att se ett märkligt försök att på egen hand simulera abstrakta metoder. Eventuellt är detta löst i Python v. 3?

self.fuel_tank = 0 return Car.TERM def get_owner(self): return self.owner def get_nr_doors(self): # Gör ingenting och ska därmed # implementeras av subklasser pass class Mazda6(Car): GEARS = 6 NR_DOORS = 4 MAX_TANK = 50 def init (self, owner, plate): # Obs anropa superklassens konstruktor Car. init (self, owner, plate) def get_nr_doors(self): return NR_DOORS return 'En ' + str(mazda6.nr_doors) + \ ' dörrars ' + Car. str (self)+ \ ', som är en Mazda 6' + \ ', och ägs av ' + self.get_owner() b = Car('Olle', 'ABC 345') print 'b är en', b m = Mazda6('pappa', 'XYZ 123') print 'm är en', m Sträng-metod get-metoder (variablerna bör vara privata) Obs, en sådan här definition kan vara bra för att tvinga alla subklasser att leva upp till ett visst gränssnitt, men gör klassen själv ofullständig. 4 Definiera klassen Mazda6 som ärver av Car Med några klassvariabler (som lämpligen betraktas som konstanter - VERSALER) Konstruktor, som i sin tur anropar superklassens konstruktor! VIKTIGT!! Obs att vi då anger argumentet self. 5 Implementation av get_nr_doors() Överskugga sträng-metoden med en specialiserad metod Skapa instanser! b är en Bil m är en En 4 dörrars Bil, som är en Mazda 6, och ägs av pappa Exempel på metoder som finns i klassen object och som vi kan överskugga: object. init (self[,...]) 6 Called when the instance is created. The arguments are those passed to the class constructor expression. If a base class has an init () method, the derived class s init () method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example: BaseClass. init (self, [args...]). object. str (self) Called by the str() built-in function and by the print statement to compute the informal string representation of an object. object. cmp (self, other) Called by comparison operations if rich comparison (see above) is not defined. Should return a negative integer if self < other, zero if self == other, a positive integer if self > other. If no 5 Det kan tyckas bisarrt att vi helt plötsligt, till skillnad från förut, ska ange argumentet self. Det har att göra med hur Python fungerar och att vi anropar superklassens init som en klassmetod (inte instansmetod). 6 http://docs.python.org/reference/datamodel.html (ganska tung artikel men säger mycket om hur Python fungerar)

cmp (), eq () or ne () operation is defined, class instances are compared by object identity ( address ) object. hash (self) Called by built-in function hash() and for operations on members of hashed collections [ ]. hash () should return an integer. The only required property is that objects which compare equal have the same hash value; [ ] 7 En av de diagnostiska datorprovsfrågorna på hemsidan, 8 illustrerar detta tydligt: Om vi i definitionen av klassen Abborre skriver class Abborre(Fisk): innebär det att A: Klassen Abborre ärver attribut och metoder från klassen Fisk. B: Klassen Fisk ärver attribut och metoder från klassen Abborre. C: Klassen Abborre ärver enbart attributen från klassen Fisk. D: Klassen Fisk ärver enbart metoderna från klassen Abborre. X: Inget av ovanstående. Jag kan avslöja att enligt facit är rätt svar A, och för vilket vettigt OO-språk som helst skulle man också otvetydigt svara A men är det här verkligen helt sant för Python? För metoderna är det onekligen så, men hur är det med instansvariabler? Låt oss se efter class Fisk: Definiera klassen Fisk def init (self): self.location = 'Mälaren' Med instansvariabel location class Haj(Fisk): def init (self): Fisk. init (self) self.species = 'Haj' class Abborre(Fisk): def init (self): self.species = 'Aborre' f = Haj() print f.location f = Abborre() print f.location Definiera klassen Haj som ärver av Fisk Anropa superklassens init Lägg till en instansvariabel Abborre ärver också av Fisk. Strunta i att anropa superklassens init Lägg till en instansvariabel Provkörning Fungerar utmärkt (skriver ut Mälaren) Detta borde väl också fungera, Abborre har ju ärvt Fisk. Men NEJ! Det kraschar med "location not defined". Instansvariabeln har alltså INTE ärvts! Ovanstående behöver förstås en kommentar. Hur kommer det sig att location inte är definierad i Abborre? Jo, för att instansvariabeln skapas dynamiskt först när konstruktorn / init verkligen körs. Och vad händer när vi instansierar Abborre? Jo, konstruktorn för Abborre körs, men konstruktorn i Fisk körs INTE! För att den ska köras måste vi explicit säga till om det, så som illustrerat i klassen Haj. Jag repeterar vad som står i dokumentationen för init: 7 hash () är intimt kopplad till eq () (eller cmp ()). Obs att objektet ska vara omuterbart! 8 Första frågan, prov nr 5.

If a base class has an init () method, the derived class s init () method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example: BaseClass. init (self, [args...]). Den här märkligheten uppstår pga. Pythons dynamiska natur (instansvariablerna skapas först i init). Även i andra OO-språk, som Java, är det av intresse att anropa superklassens konstruktor för att få hjälp med initialiseringen. Däremot så ärvs instansvariablerna i den mening att de alltid existerar i subklassen (men måhända oinitialiserade). Vi kan konstatera att enbart utifrån raden "class Abborre(Fisk):" kan vi faktiskt inte veta om instansvariablerna ärvs! Fler frågor Vad skapas av satsen nedan? <pre> barnfilm = Film("Lilla Kycklingen", 81) <s1> A: Ett objekt med två klassattribut. </s1><s2> B: Ett objekt med två statiska metoder. </s2><s3> C: Bara ett objekt, vi kan inte få ut information om objektets attribut eller metoder från ovanstående sats. </s3><s4> D: Ett objekt med två metoder. Betrakta följande kod: class Skolan(object): def init (self,adress): self.adress = adress def ret_adress(self): return self.adress class Tekniska(Skolan): return "teknis" s=skolan("osquars backe 2") k=tekniska("lindstedsv 5") print k.ret_adress() Vad kommer att hända när programmet körs? <s> <s1> A: Skrivs på skärmen "Osquars backe 2" </s1><s2> B: Programmet kommer att krascha för att metodern <code>ret_adress</code> finns inte definierad i klassen Tekniska. </s2><s3> C: Skrivs på skärmen "teknis" </s3><s4> D: Skrivs på skärmen "Listedsvägen 5" Varför är det bra att skapa egna moduler?

<s1> A: Modulerna kan återanvändas i andra program. </s1><s2> B: Man slipper använda variabler. </s2><s3> C: Felsökning förenklas. </s3><s4> D: Progrmmet blir överskådligare. Anta att vi håller på att definiera en metod i klassen Semla, där <pre> class Semla(Bakverk): Hur gör man för att anropa en metod i Bakverk inifrån Semla? <s1> A: Importerar en modul. </s1><s2> B: Definierar en ny klass. </s2><s3> C: Tar bort parametrarna i metodanropet. </s3><s4> D: Använder funktionen super. Tkinter och grafik (s. 291 ff.): from Tkinter import * import random root = Tk() c = Canvas(root) x1, y1 = 0, 0 # från-koordinater x2, y2 = None, None # till-koordinater for i in range(100): x2 = random.randrange(100) y2 = random.randrange(100) c.create_line(x1, y1, x2, y2) x1, y1 = x2, y2 c.pack() root.mainloop() print 'slut' Skapa rotobjektet Skapa en Canvas = rityta (obs det genomgående mönstret för s.k. widgets i Tkinter: första argumentet är en referens till den omgärdande behållaren) Rita en linje (slumpmässig slutpunkt) Slutpunkten blir vår nya utgångspunkt pack(), "placerar" objektet Här börjar Tkinter jobba med att framställa grafiken. Problem: anropet till mainloop() "blockerar", 9 vilket gör att 'slut' inte skrivs ut förrän vi stänger fönstret. Vad göra? Det finns två lösningar till ovanstående problem: 1) Man skapar egna s.k. "trådar" som i princip är parallella exekveringar, där vi alltså kan göra något samtidigt som mainloop() kör. (Kanske inte så aktuellt till att börja med) 2) Vi definierar s.k. call-back-metoder, som anropas av systemet (Python), och därmed ger oss kontroll när användaren har gjort något intressant på skärmen, t.ex. tryckt en knapp. Kallas även "Event-Driven Programming". Exempel med alternativ 2: 9 Man säger att ett anrop "blockerar" om programexekveringen stannar. Anrop till input() är ett annat exempel.

from Tkinter import * class App: def init (self, master): frame = Frame(master) frame.pack() self.button = Button(frame, text="quit", fg="red", command=master.destroy) self.button.pack(side=left) self.hi_there = Button(frame, text="hello", command=self.say_hi) self.hi_there.pack(side=left) def say_hi(self): print "hi there, everyone!" root = Tk() app = App(root) root.mainloop() En klass som representerar våra miniapplikation Den har en ram med en quit-knapp med callback till master.destroy (stänger applikationen) 10 och en hej-knapp med callback till self.say_hi 11 Här definierar vi say_hi som alltså kommer att anropas när användaren klickar hejknappen! Detta anrop blockerar som vanligt, men knapparna kommer att ge oss nödvändig kontroll när de trycks! 10 Se http://www.daniweb.com/forums/thread66698.html# för destroy, men det kanske finns bättre sätt? 11 Obs, när funktionens namn inte följs av parenteser så är det en metod/funktions-referens och inte ett anrop (själva anropet gör Tkinter när knappen trycks). Man kan göra anropet explicit via ett lambdauttryck, men det kanske känns ännu konstigare: command=lambda:self.say_hi().