- Komposiittityypit - Object (Mukaanlukien funktiot) - Array. - Erikoisdatatyypit - null - undefined



Samankaltaiset tiedostot
Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Javan perusteita. Janne Käki

9. Periytyminen Javassa 9.1

Java kahdessa tunnissa. Jyry Suvilehto

15. Ohjelmoinnin tekniikkaa 15.1

Olio-ohjelmointi Javalla

TIE Principles of Programming Languages CEYLON

Poikkeustenkäsittely

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

ELM GROUP 04. Teemu Laakso Henrik Talarmo

12. Monimuotoisuus 12.1

14. Poikkeukset 14.1

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

9. Periytyminen Javassa 9.1

14. Poikkeukset 14.1

Metodien tekeminen Javalla

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Taulukot. Jukka Harju, Jukka Juslin

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

12. Monimuotoisuus 12.1

Ohjelmointi 2 / 2010 Välikoe / 26.3

15. Ohjelmoinnin tekniikkaa 15.1

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Groovy. Niko Jäntti Jesper Haapalinna Group 31

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

T Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

Ohjelmoinnin jatkokurssi, kurssikoe

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

Ohjelmoinnin peruskurssien laaja oppimäärä

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

Mikä yhteyssuhde on?

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Osoitin ja viittaus C++:ssa

Java-kielen perusteet

List-luokan soveltamista. Listaan lisääminen Listan läpikäynti Listasta etsiminen Listan sisällön muuttaminen Listasta poistaminen Listan kopioiminen

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Ohjelmointi 1 Taulukot ja merkkijonot

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Kielioppia: toisin kuin Javassa

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

815338A Ohjelmointikielten periaatteet

7. Oliot ja viitteet 7.1

1. Omat operaatiot 1.1

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

TIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli

Koka. Ryhmä 11. Juuso Tapaninen, Akseli Karvinen. 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

C# olio-ohjelmointi perusopas

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Harjoitustyö: virtuaalikone

Java-kielen perusteet

Muuttujat ja kontrolli. Ville Sundberg

Ohjelmoinnin perusteet Y Python

Tenttikysymykset. + UML-kaavioiden mallintamistehtävät

A TIETORAKENTEET JA ALGORITMIT

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

Ohjelmoinnin peruskurssi Y1

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Ohjelmointiharjoituksia Arduino-ympäristössä

Pong-peli, vaihe Aliohjelmakutsu laskureita varten. 2. Laskurin luominen. Muilla kielillä: English Suomi

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

1 Tehtävän kuvaus ja analysointi

ITKP102 Ohjelmointi 1 (6 op)

Harjoitus 3: Flash-komponenttiarkkitehtuuri ( )

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

JavaScript alkeet Esimerkkikoodeja moniste 3 (Metropolia 11/2011)

7. Näytölle tulostaminen 7.1

Ruby. Tampere University of Technology Department of Pervasive Computing TIE Principles of Programming Languages

P e d a c o d e ohjelmointikoulutus verkossa

ITKP102 Ohjelmointi 1 (6 op)

Periytyminen (inheritance)

Mitä poikkeuskäsittely tarkoittaa?

Dart. Ryhmä 38. Ville Tahvanainen. Juha Häkli

20. Javan omat luokat 20.1

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Java-API, rajapinnat, poikkeukset, UML,...

Esimerkki: Laskin (alkua) TIEA341 Funktio ohjelmointi 1 Syksy 2005

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Rajapinta (interface)

7/20: Paketti kasassa ensimmäistä kertaa

Kooste. Esim. Ympyrän keskipiste voidaan ajatella ympyrän osaksi.

Testivetoinen ohjelmistokehitys

17. Javan omat luokat 17.1

D-OHJELMOINTIKIELI. AA-kerho, 33. Antti Uusimäki. Arto Savolainen

16. Javan omat luokat 16.1

Ohjelmistotekniikan menetelmät, suunnittelumalleja

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

Digitaalisen median tekniikat. Luento 4: JavaScript

Transkriptio:

Ohjelmointitekniikka Tyyppiturvallisuuden tavoittelua Javascriptissa muuttujat ovat tyypittömiä, mutta arvoilla on tyyppi. Muuttuja esitellään var -avainsanalla ja muuttujan tyypin arvoa ei erikseen määritellä. Datatyyppejä ovat javascriptissa seuraavat: - Primitiivityypit - String - Number (Huomaa, että kokonais- ja liukulukuja ei ole eroteltu. Numbereihin kuuluu myös erikoisarvot Infinity ja NaN eli not a number ) - Boolean - Komposiittityypit - Object (Mukaanlukien funktiot) - Array - Erikoisdatatyypit - null - undefined Koska javascript on heikosti tyypitetty kieli, tyypityksen pakottamista pidetään huonona tyylinä ja kielen paradigman vastaisena toimintana. Kuitenkin on tapauksia, joissa esimerkiksi syötteenä saadun arvon tulisi olla jotain tiettyä tyyppiä ja javascriptin automaattinen castaus ei tuota haluttua tulosta. Esimerkiksi verkkokaupassa ei yleensä tulisi voida käyttää liukulukuja kappaletavaran ostomäärää syöttäessä. Tällaisissa tilanteissa tyypin tarkistaminen on paikallaan. Javascriptissa on kaksi eri yhtäsuuruusoperaatiota === ja ==, joista ensimmäinen tarkistaa onko arvot samaa tyyppiä ja sen jälkeen vertailee niitä, jälkimmäinen pyrkii muuttamaan ne saman tyyppiseksi ja sen jälkeen vertailee niitä. Yleinen konsensus on, että kahta yhtäsuuruusmerkkiä tulisi välttää ja käyttää mieluummin kolmea. true == 1; //true

true === 1; //false Javascriptin tyyppitarkastukset voisi toteuttaa seuraavasti: // Tarkistaa, onko annettu arvo kokonaisluku. function isinteger(value) { return isnumber(value) && value%1===0; // Tarkistaa, onko annettu arvo numeraali. function isnumber(value) { return typeof(value)==="number" &&!isnan(value); // Tarkistaa, onko annettu arvo taulukko. function isarray(a) { return (a instanceof Array); // Tarkistaa, onko annettu arvo taulukko joka sisältää vain kokonaislukuja. function containsonlyintegers(a) { if (!isarray(a)) return false; for (var i = 0; i < a.length; i++) { if (!isinteger(a[i])) return false; return true; // Tarkistaa, onko annettu arvo boolean. function isboolean(value) { if(value === true value === false){ return true; else return false; // Tarkistaa, onko annettu arvo taulukko joka sisältää vain numeraaleja. function containsonlynumbers(a) { if (!isarray(a)) return false; for(i = 0; i<a.length; i++){ if(!isnumber(a[i])) return false; return true;

// Tarkistaa, onko annettu arvo merkkijono. function isstring(a) { return typeof(a) == "string"; Algoritmit, funktiot ja sulkeumat, poikkeusten käsittely Funktion muuttujat on hyvä määritellä heti alussa vaikka se olisi vain loopin indeksi, koska se näkyy joka tapauksessa kaikkialla funktion sisällä (Tosin, uusimmissa Javascriptin versioissa on let -avainsana, jolla muuttujan näkyvyys voidaan rajata vain tiettyyn ohjelmalohkoon). Muuttujat tulee määritellä var:n avulla, koska globaaleja muuttujia tulee välttää jos niitä ei tarvitse. Tämä selkeyttää toiminnallisuutta ja vähentää riskiä asettaa ja käyttää vahingossa globaaleja muuttujia, vaikka tarkoitus olisi ollut käyttää paikallisia. Javascript ei suoraan tue yksityisiä muuttujia, mutta niitä voidaan simuloida sulkeumien avulla: function Konstruktori(){ var _privaattimuuttuja ="private";//jos muuttujan on tarkoitus olla privaatti, on //se tapana nimetä _ alkuiseksi, vaikka sitä ei olisikaan suojattu this.julkinenmuuttuja ="public"; this.getprivatevar=function(){ return _privaattimuuttuja; var olio = new Konstruktori(); write(olio.julkinenmuuttuja); write(olio._privaattimuuttuja); write(olio.getprivatevar());

Esimerkissä privaattimuuttujaan päästään käsiksi ainoastaan aksessorin GetPrivateVar():n avulla. Koska javascriptissa yksityisten muuttujien simulointi on suhteellisen monimutkaista sekä hieman hackilta vaikuttavaa, suosittelisimme niiden välttämistä, jollei niiden käytölle ole hyvää syytä. Lisäksi yksityisten muuttujien toteutus tällä tavoin rajoittaa javascriptin leimallista dynaamisuutta ja avoimuutta sekä testattavuutta. Käyttäjän antamat syötteet tulisi aina tarkistaa. Ohjelmoijan vastuulla on tarkastaa muuttujien, parametrien ja funktioiden tyyppi. Julkisissa kirjastoissa olisi hyvä tarkistaa tyypit, jotta niitä ei voisi käyttää väärin. Tyypittömyydestä voi joissakin tilanteissa olla hyötyä, joten aina ei tarvitse pyrkiä javamaiseen tyyliin. Voi tehdä funktioita joiden toiminnallisuus riippuu parametrien tyypeistä. Esimerkki tyypittömyyden eduista: function palauta(){ return 5; function tuplaa(a){ return a*2; tuplaa(2); //4 tuplaa(palauta()); //10 tuplaa(2.2); //4.4 tuplaa(true); //2 var luku = prompt( anna luku ); // kun luku tulee käyttäjältä if isnumber(luku) { tuplaa(a);

Funktionaalinen vs imperatiivinen Imperatiivinen ohjelma toimii yleisesti nopeammin kuin funktionaalisesti tehty. Jos on kyse pienemmästä laskennasta niin sen tekeminen funktionaalisesti on usein selkeämpää. Lisäksi funktionaalisuudella voidaan tehostaa koodin uusiokäyttöä ja geneerisyyttä: function foreach(array, action) { for (var i = 0; i < array.length; i++) action(array[i]); foreach(["wampeter", "Foma", "Granfalloon"], print); Lähde: http://eloquentjavascript.net/chapter6.html Toisaalta tiukasti imperatiivisesti toteutettu javascript ohjelma ei hyödynnä kaikkia javascriptin vahvuuksia, joten saman tien voisi ohjelmassaan käyttää jotain toista kieltä. Ohjenuoramme on, että kumpiakin tyylejä voi käyttää, kunhan tietää että mitä käyttää milloin ja kirjoittaa selkeää ohjelmakoodia. Pieni funktionaalinen ohjelmaesimerkki: function laske(funktio, arvo) { return funktio(arvo); var plus5 = function(x) { x = x + 5; return x; var double = function(x) { x = x * 2; return x; write(laske(plus5, 1)); // 6 write(laske(double, 5)); // 10

Sulkeumat Sulkeuma on hyvin vahva ohjelmointitekniikka. Sulkeumalla voidaan rajata funkioiden ja muuttujien näkyvyyttä. Sulkeumia voi hyödyntää kuten kapselointia kätkemällä tietyn komponentin toteutus mutta tarjoamalla käyttörajapinnan. Seuraavassa esimerkissä teelaskuri olioilla on tallessa oman x arvo. // palauttaa sulkeuman, jossa kenttä x sekä kasvataarvoa funktio function teelaskuri() { var x=0; return { 'x': 0, 'kasvataarvoa' : function() { this.x++; var laskuria = teelaskuri(); write("laskuri A = " + laskuria.x); // 0 laskuria.kasvataarvoa(); write("laskuri A = " + laskuria.x); // 1 laskuria.kasvataarvoa(); write("laskuri A = " + laskuria.x); // 2 var laskurib = teelaskuri(); write("laskuri B = " + laskurib.x); // 0 laskurib.kasvataarvoa(); write("laskuri B = " + laskurib.x); // 1 write("laskuri A = " + laskuria.x); // 2 Poikkeukset Try-Catch korkealla tasolla (Sovellus, client-side), Throw matalalla (Työkalut, kirjastot). http://www.devhands.com/2008/10/javascript-error-handling-and-generalbest-practices/ Miksi käyttää Throwia, kun voi käyttää if-elseä? Throw luo Error -olion jonka funktioista voi olla hyötyä virheen korjaamiseksi.

Oliot ja periytyminen Javascriptissä ei ole luokkia, joten ns. klassista perintää kuten Javassa ja C++:ssa ei ole. Javascriptin perintä perustuu prototyyppeihin. Perintää käytetään jäsentämään ohjelmakoodia. Syitä perinnän käyttämiselle ovat muunmuassa koodin uusiokäyttö ja polymorfismi. 3 oliota, eläin, nisäkäs ja lammas, asetetaan nisäkäs perimään eläimen ominaisuudet, sekä lammas perii nisäkkään ominaisuudet. Nyt lampaalla on nisäkkään, sekä elaimen ominaisuudet. function Elain(paino = 5) { this.ika = 0; this.paino = paino; Elain.prototype.asetaPaino = function (maara) {this.paino = maara Elain.prototype.asetaIka = function (maara) {this.ika = maara Elain.prototype.ikaanny = function() {this.ika++; function Nisakas() { this.poikaset = 0; Nisakas.prototype = new Elain(); Nisakas.prototype.synnyta = function() {this.poikaset++ function Lammas() { this.villaa = 100; Lammas.prototype = new Nisakas(); Lammas.prototype.keraaVillaa = function() { var maara = this.villaa; this.villaa = 0; return maara; Lammas.prototype.ikaanny = function() { this.ika++; this.villaa += 10; this.paino += 5;

var lammas = new Lammas(); lammas.asetapaino(50); // paino 50 lammas.asetaika(7); // ikä 7 lammas.synnyta(); // poikaset 1 write(lammas.villaa); // 100 var villaa = lammas.keraavillaa(); write(villaa); // 100 write(lammas.villaa); // 0 lammas.ikaanny(); // villaa 10, ika 8, paino 55 kk(lammas); // Javascriptissä voidaan laittaa lampaalle uusi ikaanny metodi var ikaantyjalammas = new Lammas(); ikaantyjalammas.asetaika(10); write(ikaantyjalammas.ika); // 10 ikaantyjalammas.ikaanny(); write(ikaantyjalammas.ika); // 11 ikaantyjalammas.ikaanny = function() { this.ika += 3; write(ikaantyjalammas.ika); // 11 ikaantyjalammas.ikaanny(); write(ikaantyjalammas.ika); // 14 write(lammas.ika); // 8 lammas.ikaanny(); write(lammas.ika); // 9 kk(ikaantyjalammas); // nyt ikaantyjalampaan prototyypissä on kenttä // ikaanny:function () { // this.ika += 3; // Prototyyppimuuttujat vs instanssimuuttujat Funktiot tulee pääsääntöisesti asettaa prototyyppiin, ennemmin kuin itse olion instanssiin. Tällöin se vie vähemmän tilaa. Kuitenkin esimerkiksi konstruktorissa välitetyt funktiot on syytä tallentaa instanssimuuttujina. Mikäli prototyypeissä on arvoja, toimivat ne oletusarvoina prototyypin

toteuttavalle oliolle. Parametreja perintäketjussa ylöspäin Kun yläluokan konstruktorissa on parametreja, voidaan aliluokan parametrit välittää yläluokalle seuraavasti: function Elain(ika) { this.ika = ika; function Lemmikkielain(ika, nimi) { this.base = Elain; //base muuttujan sijasta voidaan kutsua konstruktoria suoraan: this.base(ika); //Elain.call(this, ika); this.nimi = nimi; Lemmikkielain.prototype = Elain; var nasu = new Lemmikkielain(5, "nasu"); write(nasu.nimi); Prototyyppiketjussa ylöspäinkulkemiseen menee aina aikaa ja siksi pitkiä prototyyppiketjuja kannattaa välttää, jos suorituskyky on kriittinen. Abstraktien funktioiden soveltamista ja simuloimista: Elain = function(paino, kasvufunktio) { this.paino = paino 0 this.kasva = kasvufunktio // function(){throw new Error('not implemented') if (this.kasva === undefined) throw new Error("Elain on abstrakti luokka!"); Elain.prototype.getPaino = function() { write(this.paino) lammas = new Elain("Fatso", function() {this.paino += "o") kroko = new Elain(25, function() {this.paino += 5) lammas.getpaino() lammas.kasva()

lammas.kasva() lammas.getpaino() kroko.getpaino() kroko.kasva() kroko.kasva() kroko.getpaino() weequ = new Elain(1337) // Error weequ.kasva() The catch? Abstraktion käyttö on Javascriptin kohdalla aivan turhaa johtuen kielen dynaamisuudesta. Olioihin voi lisätä funktioita sekä poistaa ja muokata niitä lennosta. Tämän kaltainen abstrakti luokka palvelee parhaimmillaankin vain jonkinlaisena referenssinä. Duck typing Javascriptissä olioita voi siis muuttaa dynaamisesti, eikä se sisällä käsitteitä kuten "luokka", "abstract" tai "interface". Tästä syystä javascriptissä kenttien tarkastukset tulee tehdä dynaamisesti toisin kuin esimerkiksi Javassa, jossa tiedetään että oliot noudattavat luokkamäärittelyä. Esimerkki dynaamisesta tarkastamisesta: function Koira() { Koira.prototype.hauku = function() { write("hau HAU!") function Kissa() { Kissa.prototype.mau = function() { write("mjiau") function can(obj, methodname) { return ((typeof obj[methodname]) == "function"); var dogi = new Koira()

if (can(dogi, "hauku")) { dogi.hauku()