TDT4100: Objektorientert Programmering
#Repetisjon
##Wrapper-class
##Modifikatorer
###Synlighetsmodifikatorer
|| __Modifikator__ || __Klasse__ || __Pakke__ || __Subklasse__ || __Verden__ ||
|| __Public__ || Ja || Ja || Ja || Ja ||
|| __Protected__ || Ja || Ja || Ja || Nei ||
|| __Default/no modifier__|| Ja || Ja || Nei || Nei ||
|| __Private__ || Ja || Nei || Nei || Nei ||
###Abstract
public final int someNumber = 10;
`someNumber` kan ikke forandres senere i koden. Eventuelt kan en ha følgende tilfelle:
public final int someNumber;
Denne variabelen kan kun initialiseres i konstruktøren, og aldri igjen etter det. Immuterbare variabler brukes ofte sammen med `static`, et nøkkelord som forklares i avsnittet under.
###Static
Dette er en viktig teknikk som handler om å kunne følge med på endringer som skjer i essensielle data som for eksempel kan forandre rekkefølgen på en sortering eller lignende. Man har en eller flere observatører som ønsker å følge med på den observerte. Den observerte må ha metoder som for å lage og sende endringshendelser, samt for å legge til og fjerne observatører til/fra en liste med alle som ønske rendringsmeldingene. Observatøren må implementere et grensesnitt av typen `EventListener`, for eksempel `PropertyChangeListener`, med metoden `propertyChange()`.
##Casting
Når man itererer gjennom en mengde, kan det være hensiktsmessig å bruke casting. For eksempel kan det være en mengde objekter som arver fra samme objekt, men der ikke alle metodene er definert for alle typene klasser.
La oss si at vi har en klasse som heter togvogn, og to klasser passasjervogn og godsvogn som begge arver fra togvogn. Passasjervogn har en metode for å telle passasjerer tellePassasjerer(). Et tog kan beskrives som en liste av vogner. Hvis vi nå ønsker å summere opp alle passasjerene i toget, nytter det ikke å iterere over hele toget og kalle på tellePassasjerer-metoden, fordi toget består også av godsvogner, som vil gi oss en error i itereringen. Da kan vi bruke casting:
for (togvogn vogn : tog) {
if (vogn instanceof passasjervogn){
passasjervogn pvogn = (passasjervogn)vogn;
antallPassasjerer += pvogn.tellePassasjerer();
}
Husker fra `Iterable<T>`-grensesnittet at denne forløkken gjelder for alle vogner av typen togvogn i en collection tog. instanceof sjekker om vognene er av typen passasjervogn, som legger til rette for selve castingen, (passasjervogn)vogn. Her tar vi en passasjervogn-instanse av vogna, ettersom vi først har sjekket instanceof. Deretter kan vi hente tellepassasjerer-metoden.
##Collection-rammeverket
Collection er et stort rammeverk som består av lister, set, maps, iterator/iterable-grensesnitt, HashMap, ArrayList m.m. Felles for Collection er en rekke metoder; her er noen av de viktigste:
|| add(T elm) || Legger til element elm av typen T til collection ||
|| addAll(Collection<T> c) || Legger alle elementene i Collection c av type T til en annen collection ||
|| clear() || Fjerner alle elementer fra collection ||
|| contains(object obj) || Returnerer true hvis col. inneholder obj||
|| containsAll(Collection<T> c) || Returerer true hvis alle elementene i c ligger i collection ||
|| isEmpty() || Returnerer true hvis collection er tom ||
|| size() || Returnerer en int med antall elementer i collection ||
|| toArray() || Returnerer en Object[] array med alle elementene i lista ||
|| remove(Object obj) || Fjerner objektet fra collection ||
###HashMap<K,V>
HashMap i Java minner veldig om Dictionary fra Python. Man har en type keys K og en type verdi V som den husker på.
###Interface Set<E>
Et Set i Java er veldig likt et set i Python, det kan ikke inneholde duplikater. For eksempel om man har en ArrayList med mange duplikter og ønsker å finne antall unike objekter i lista kan man legge alle elementene fra ArrayList’n til et Set.
liste.add(Obj...obj);
Set<String> set1 = new HashSet<>();
liste.clear();
##Interface Comparable<T>
public class testKlasse implements Comparable<T>{
// som må inneholde metoden
public int compareTo(T objekt){......}}
##Interface Comparator<T>
Er ment å implementeres av en annen klasse enn den som skal sorteres. Den kan da også ha friere regler på utfallet av sammenligninger. For å bruke en Comparator sendes den enkelt med som et andre argument til kallet til Collections.sort(). Comparator-grensesnittet krever at du har implementert metoden compare(o1,o2). Denne har samme logikk for returverdien som compareTo(), men tar en inn to argumenter istedet for at et argument sammenlignes med "this". I motsetning til Comparable, kan man bestemme sorteringsrekkefølge, utenom dette er logikken den samme. [Eksempelkode](https://www.ntnu.no/wiki/display/tdt4100/Sortering+med+Comparable+og+Comparator)
Comparator går hånd i hånd med lambda-uttrykk, som man kan [lese mer om her](https://www.ntnu.no/wiki/display/tdt4100/Lambda-uttrykk+og+funksjonelle+grensesnitt+i+Java+8)
@Override
public int compare(Person a, Person b) {
return a.getAge() - b.getAge();
persons.sort((a, b) -> a.getAge() - b.getAge());
Men serr, les mer på [wiki-sida](https://www.ntnu.no/wiki/display/tdt4100/Lambda-uttrykk+og+funksjonelle+grensesnitt+i+Java+8).
##Interface Iterable<T>
action();
@Override
public Iterator<T> iterator() { return c.iterator();}
##Interface Iterator<E>
En instans av iterator-grensesnittet, altså en Iterator, kan brukes til å iterere gjennom elementer til et annet objekt. Det viktige å merke seg her er at en Iterator husker hvor langt man har kommet i itereringen, og at etter itereringen er gjennomført er iteratoren oppbrukt. Iterator-grensesnittet ligger i Collection-rammeverket og har følgende tre metoder:
boolean hasNext()
som returnerer true hvis det er flere elementer igjen å iterere gjennom.
<E> next()
returnerer neste elementer og tar et steg videre i iteratoren. Ikke bruk denne med mindre hasNext() returnerer true.
void remove()
som fjerner det siste elementet som ble returnert av next() fra collection-kilden om den støtter det.
##Exceptions
Her er det viktig å skille mellom checked exceptions og unchecked exceptions.
###Checked exception
Enkelt forklart er dette feilene som blir oppdaget ved kompilering. Eksempler er IOException, SQLException, DataAccessException, ClassNotFoundException, InvocationTargetException og MalformedURLException.
Løsningen på checked exceptions er ofte å legge koden i en try/catch:
try{
etellerannet
}catch(IOException e){}
###Unchecked exception
Dette er exceptions som ikke blir verifisert iløpet av kompileringen, og skyldes dårlig programmering. Eksempler er NullPointerException, ArrayIndexOutOfBound, IllegalArgummentException, IllegalStateException, Her også kan man ofte løse problemet med at prve en try/catch, og huske å bruke throw.
##Input og output
Her benytter vi oss stort sett av subklasser av InputStreamReader og OutputStreamWriter. Her snakker jeg om Reader og Writer, som igjen arver til FileReader og FileWriter. Personlig foretrekker jeg PrintWriter, da den har en utvidet print-metode som dekker boolean, strings, chars, ints alt. Veldig kjekk metode er println (leses: print-line), som først printer og deretter går til ny linje.
Når man skal velge fil fra datamaskin som det skal skrives til, kan man bruke JFileChooser (ikke veldig eksamensrelevant).
JFileChooser chooser = new JFileChooser();
if(chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();
// deretter kan man
try {
PrintWriter outprint = new PrintWriter(selectedFile);
outprint.println(“Hello World”);
out.close();
catch (FileNotFoundException e) {
e.printStackTrace();
}
Samme gjelder når man skal lese fra fil, men da bruker man FileReader og .read() isteden for PrintWriter og println().
##Småplukk
Når en metode skal ta inn et uspesifisert antall elementer, skriver man slik:
public Constructor(Obj...obj)
som lager en String array obj[]. Deretter kan man for eksempel lage en ArrayList slik:
this.someList = new ArrayList<Obj>(Arrays.asList(obj));
Et funksjonelt grensesnitt har èn abstrakt metode (kalt den funksjonelle metoden), som legger til rette for lambda-uttrykk.
Leses: Er a større enn b? true gir a. ellers: b.
_Delegering_:
Har et interface man kan implementere i f.eks. en standardklasse for grensesnittet.
Deretter kan en annen klasse, som ikke implements interface, lage et felt som instansierer et standardklasse-objekt,
det objektet kan igjen brukes i metoder i den vanlige klassens metoder som ligner på metodene i interfacet / implementarsjonsklassen/standardklassen.
På den måten kan standardklasse-objektet enkelt byttes ut, som gjør delegeringsteknikken mer fleksibel enn arv.
I en løkke: bruk break for å stoppe itereringen, og bruk continue for å hoppe til neste ledd i iterasjonen.
##Diagrammer
###Objektdiagram
Objektdiagrammer viser tilstanden til objekt(struktur)er, med verdiene til attributter og referanser som knytter objekter sammen.
###Objekttilstandsdiagrammer
Objekttilstandsdiagrammer viser hvordan objekt(struktur)er endres over tid, når en kaller metoder.
###Klassediagrammer
Klassediagrammer er en illustrasjon av innholdet i og sammenhengen mellom klasser, som et supplement til tekslig kode. Et klassediagram viser klasser som bokser, attributter og operasjoner som tekstlinjer inni boksene (i hver sine deler) og assosiasjoner og arv som streker med. I tillegg annoteres assosiasjonsstreker med informasjon om navn og såkalt multiplisitet (også kalt kardinalitet).
##Testing med JUnit
public void TestNumber(){
Number number = new Number();
assertEquals(1, number.getNumber());
}
##Bruk av this()
private final int age, height;
public Person(String firstName, String lastName, int age, double height){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
public Person(){
##Scanner
Ved iterering brukes ofte `while(scanner.hasNextLine())`, forså å lage en ny streng av neste linje og manipulere denne: `String line = scanner.nextLine();` Må alltid huske å lukke scanneren etter bruk `scanner.close();`