Objektorienterad Programmering (TDDC77)
Föreläsning IX: Klasser och Objekt, Instantiering
Ahmed Rezine
IDA, Linköpings Universitet
Hösttermin 2017
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Förkunskaper från tidigare föreläsningar:
I STONE
I Variabler, datatyper, typkonvertering
I Logiska och matematiska uttryck
I Metoder-returvärde och parametrar
I Villkorssatser if/else
I Loopar, for, while, do-while
I Arrayer, String
Vad händer i resten av kursen:
I Klasser och objekt (classes and objects)
I Inkapsling och arv (encapsulation and inheritance)
I Åsidosättning och överlagring (overriding and overloading)
I Abstrakta klasser och gränssnitt (abstract classes and interfaces)
I Samlingar (collections), generics
I Uppräkningar (enumerations)
I Undantag (exceptions)
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Objekt
I Identitet : Typ och referens
I Tillstånd: Variabler
I Tjänster: Metoder
Ett objekt
Identitet
Tillstånd Tjänster
Ett objekt
Typ och referens
Variabler Metoder
Klasser av objekt
I Varje objekt som skapas måste höra till en klass
I Klassen definierar hur objekten fungerar, det vill säga deras beteende. Lite som en mall för objekten
I En klass skapas genom att man definierar den. Varje klass i en separat fil.
I Klassens namn blir objektens typ
/* G r e e t e r . j a v a
* E n k e l K l a s s som r e p r e s e n t e r a en p e r s o n som
* h ä lsa med ett s p e c i f i k t m e d d e l a n d e
*/
c l a s s G r e e t e r {
p r i v a t e S t r i n g m e s s a g e ;
p u b l i c G r e e t e r (S t r i n g msg ){
m e s s a g e = msg ; }
p r i v a t e S t r i n g s p e a k (){
r e t u r n m e s s a g e + " !!! ";
} }
Objekt
I Ett objekt kan även kallas instans (förekomst) av en klass.
I När man skapar ett objekt som tillhör en viss klass så säger man att man instantierar klassen
I Varje objekt tar sina egna “kopior” av variablerna som definierades i klassen. Dessa bestämmer objektets tillstånd
I Ett objekt skapas med nyckelordet new
/* D r i v e r . j a v a
* D e k l a r e r a och anv ä nda sig av G r e e t e r p r o g r a m m e t
*/
c l a s s D r i v e r {
p u b l i c s t a t i c v o i d m a i n (S t r i n g[] a r g s ){
G r e e t e r p e r s o n = n e w G r e e t e r (" hej ");
G r e e t e r g l a d = n e w G r e e t e r (" h e j h e j ");
S y s t e m . out . p r i n t l n (" p e r s o n G r e e t e r s a y s : "
+ p e r s o n . m e s s a g e );
S y s t e m . out . p r i n t l n (" g l a d G r e e t e r s a y s : "
+ g l a d . s p e a k ( ) ) ; }
}
Pac-man
Exampel
i m p o r t j a v a . u t i l . S c a n n e r ;
c l a s s G a m e {
s t a t i c S c a n n e r s c a n = n e w S c a n n e r ( S y s t e m . in );
s t a t i c G h o s t g r e e n G h o s t = n e w G h o s t (" g r e e n ", 1 , 4);
s t a t i c G h o s t b l u e G h o s t = n e w G h o s t (" b l u e ", 0 , 3);
p u b l i c s t a t i c v o i d m a i n (S t r i n g[] a r g s ) { S t r i n g c o m m a n d ;
do{
// ask the g h o s t s to u p d a t e t h e r e c o o r d i n a t e s g r e e n G h o s t . u p d a t e ();
b l u e G h o s t . u p d a t e ();
// p r i n t the new c o o r d i n a t e s
S y s t e m . out . p r i n t l n ( g r e e n G h o s t . p r i n t ( ) ) ; S y s t e m . out . p r i n t l n ( b l u e G h o s t . p r i n t ( ) ) ; // c h e c k if the u s e r w a n t s to q u i t
S y s t e m . out . p r i n t (" \ n W r i t e \" c \" if you w a n t to c o n t i n u e : ");
c o m m a n d = s c a n . n e x t ();
}w h i l e( c o m m a n d . e q u a l s I g n o r e C a s e (" c "));
} }
Exampel
c l a s s G h o s t {
S t r i n g n a m e ; i n t col =0 , row =0;
p u b l i c G h o s t (S t r i n g name , i n t _col , i n t _ r o w ){
t h i s. n a m e = n a m e ; col = _ c o l ; row = _ r o w ; }
p u b l i c v o i d u p d a t e (){
col = (t h i s. col = = 9 ? col -1: col + 1 ) ; row = ( row = = 9 ? row -1: row + 1 ) ; }
p u b l i c S t r i n g p r i n t (){
r e t u r n n a m e + " : ( " + row + " , " + col + " ) ";
} }
Static
I Tidigare har vi skrivit static lite överallt
I Från och med nu så kommer vi att använda oss mycket mindre av static
I Till exempel när vi skriver main-metoden
Två sorter variabler:
I För att förstå vad nyckelordet static innebär behöver man veta att det i själva verket finns ytterligare ett sätt att indela variabler i två kategorier som anknyter till objekt och klasser
I De två nya kategorierna kallas instans och klassvariabler
I Tidigare gjorde vi uppdelningen primitiva typer och referenstyper. Detta har ingenting med instans och klassvariabler att göra
Instansvariabler
I En instansvariabel är individuell för varje instans av en klass
I Det är denna sorts variabler ni i fortsättningen ska använda i nästan alla fall
I Deklareras utan nyckelorder static
c l a s s T e s t 1 { i n t a = 0;
v o i d use (){
S y s t e m . out . p r i n t l i n e ( a );
} }
Klassvariabler
I En klassvariabel är gemensam för alla instanser av en klass.
I Denna sorts variabler ska ni undvika
I Deklareras med nyckelorder static
c l a s s T e s t s 2 {
s t a t i c i n t a = 0;
v o i d use (){
S y s t e m . out . p r i n t l i n e ( T e s t 2 . a );
} }
Funktioner då?
I Principen är densamma för funktioner
I Funktioner deklarerade utan static hör samman med (och opererar på) enskilda instanser, anropas med
objekt.funktionsNamn()
I Funktioner deklarerade med static hör samman med (och opererar på) klassen, anropas med
KlassNamn.funktionsNamn()
I Detta innebär i förlängningen att funktioner deklarerade med static inte kan komma åt variabler deklarerade utan static eftersom det inte är specificerat vilken instans instansvariabel som avses
Exempel?
I Kan du hitta på några egna exempel på klassmetoder och instansmetoder du använt?
I Klassmetoder Math.max(), Math.round(), alla era lincalcmetoder
I Instansmetoder strängen.charAt(), objektet.equals(), ...
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Att instansiera en klass
I Man instansierar (skapar ett objekt av) en klass genom att anropa en konstruktor
I Detta sker genom att använda nyckelordet new följt av klassnamn och parameterlista
I Det kan finnas flera konstruktorer med olika parameterlistor
I Exakt en instans skapas för varje gång man kör konstruktorn
G r e e t e r g l a d = n e w G r e e t e r (" h e j h e j ");
G r e e t e r c o m p i s = n e w G r e e t e r (" t j a b a ");
Objekt
G r e e t e r g l a d = n e w G r e e t e r (" h e j h e j ");
G r e e t e r c o m p i s = n e w G r e e t e r (" t j a b a ");
Greeter
hejhej speak()
Greeter
tjaba speak()
glad compis
Konstruktorer
I En konstruktor saknar returtyp och heter samma som klassen
I Om ingen konstruktor skrivs så skapas automatiskt en så kallad standardkonstruktor som inte tar några argument
I Om man skapar en egen konstruktor så skapas inte standardkonstruktorn automatiskt
I Man kan ha godtyckligt många konstruktorer så länge de har olika parameterlistor
I Detta gäller generellt för alla funktioner och kallas överlagring (tas upp senare)
Referenser
I Objekt är referenstyper,det betyder att när man skapar ett objekt egentligen man får en referens tillbaka
I Gör man sedan en tilldelning eller jämförelse så är det referensen som jämförs
G r e e t e r j o h n = n e w G r e e t e r (" God morgon , jag h e t e r J o h n S m i t h ! ");
G r e e t e r j o h n s m o r = j o h n ; G r e e t e r j o h n s f a r = j o h n s m o r ;
Flera referenser - samma objekt
Greeter
“... jag heter John ...” speak()
john
johnsmor johnsfar
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Åtkomst
I I Java finns fyra åtkomstnivåer för variabler och funktioner
I public : alltid synlig
I protected: tas upp senare
I default (package): tas upp senare
I private: endast synlig inom klassen
I i den här kursen håller vi oss till public och private
Åtkomst grundregel
I Deklarerar alla variabler som private
I Deklarerar alla funktioner som public
I Detta bettyder att om man vill kunna läsa/skriva en variabel från en annan klass så måste man göra funktioner som utför det. Detta kallas för getters och setters och eclipse kan generera den automatiskt
I Det finns undantag, men dessa kommer ni att lära er att känna igen så småningom
I Konstruktorer bör vara deklarerade som public
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Calculator
p u b l i c c l a s s C a l c u l a t o r {
p r i v a t e d o u b l e memory , r e s u l t ;
p u b l i c d o u b l e add (d o u b l e a ){
r e s u l t = a + m e m o r y ; r e t u r n r e s u l t ; }
p u b l i c v o i d s t o r e (){
m e m o r y = r e s u l t ; }
p u b l i c d o u b l e g e t M e m o r y (){
r e t u r n m e m o r y ; }
}
Ett objekt
Identitet
Tillstånd Tjänster
Ett objekt
Calculator
memory, result add(), store()
Använda kalkylatorn
C a l c u l a t o r c a l c = n e w C a l c u l a t o r ();
c a l c . add (2.3 , 5);
Flera konstruktörer till Calculator
p u b l i c c l a s s C a l c u l a t o r {
p r i v a t e d o u b l e memory , r e s u l t ; p u b l i c C a l c u l a t o r () {
r e s u l t = 0;
m e m o r y = 0;
}
p u b l i c C a l c u l a t o r (d o u b l e l o a d e d M e m ){
r e s u l t = 0;
m e m o r y = l o a d e d M e m ; }
...
Outline
Klasser och Objekt Instansiering Åtkomst Calculator Abstrakt datatyp
Abstrakt datatyp
I Ibland vill man behandla data på ett sätt som inte riktigt stämmer med de primitiva datatyperna.
I Man måste då “kombinera ihop” en ny datatyp som är anpassad för det man faktiskt vill göra med den
I Ett exempel på detta är stacken som ni implementerade till lincalc
I En abstrakt datatyp är ofta en kombination av variabler (tillstånd) och funktioner (tjänster) ...
I ... det låter som att abstrakta datatyper och klasser har en del gemensamt
Öva - gör om stacken som en klass
I Skapa en klass StringStack som kan lagra 100 strängar
I Strängarna ska lagras i en Array som det inte ska gå att ändra i så att stacken hamnar i ett otillåtet tillstånd
I Ska klara operationerna push, pop och isEmpty
StringStack
p u b l i c c l a s s S t r i n g S t a c k {
p r i v a t e s t a t i c i n t MAX = 1 0 0 ;
p r i v a t e S t r i n g[] d a t a = n e w S t r i n g[ MAX ];
p r i v a t e i n t pos = 0;
p u b l i c b o o l e a n i s E m p t y (){
r e t u r n pos == 0;
}
p u b l i c v o i d p u s h (S t r i n g s ){
d a t a [ pos ++] = s ; }
p u b l i c S t r i n g pop (){
r e t u r n d a t a [ - - pos ];
} }