Programowanie obiektowe Wykład 4
Tworzenie własnych obiektów Słowo kluczowe this W JavaScriptmożna tworzyć własne obiekty. Wykorzystuje się tu zapis utworzonej funkcji o nazwie takiej samej jak klasa, dla której definiujemy właściwości(zmienne proste lub obiektowe) i metody(funkcje wewnętrzne). Nadając i wykorzystując identyfikatory właściwości i metod korzystamy ze słowa kluczowego this.rozumiane jest ono jako obiekt bieżący, właściciel metody lub właściwości. Poniżej prosty przykład:
Przykład <HTML> <HEAD> </HEAD> <BODY style="font-size:18px"> <P> AKAPIT</P> <PRE> <SCRIPT language="javascript"> function kolor1( ) { this.document.bgcolor = "red"; function kolor2(e) { e.style.color = "yellow"; </SCRIPT> </PRE> <INPUT type="button" value="kolor dla tła okna" onclick="kolor1( )"> <INPUT type="button" value="kolornapisu przycisku" onclick="kolor2(this)"> </BODY> </HTML>
W powyższym przykładzie mamy dwie własne funkcje. W pierwszej o nazwie kolor1 ustalamy kolor tła dla bieżącego obiektu (this) - którym jest domyślnie window. Druga funkcja o nazwie kolor2 zmienia kolor czcionki przekazanego do funkcji obiektu e - wywoływana jest kliknięciem w przycisk z przekazaniem odniesienia do tego właśnie przycisku (this), a więc zmienia się kolor napisu na przycisku.
var piesek1 = { ; Najmniej uniwersalny sposób - tworzenie konkretnej instancji (egzemplarza) bez definicji: imie: "Maja", rasa: "kundel", kolor: "zółty", plec: "suczka", glos:"haaaauuuu", dajglos: function () { document.writeln(this.glos); document.writeln(piesek1.imie); piesek1.dajglos ();
Definicja konstruktora obiektu - Metoda 1 Można utworzyć definicję tzw. konstruktorobiektu (klasa) wykorzystując własną funkcję: functionnazwa(argument1,argument2, itd) { this. właściwość1 = argument1; this. właściwość2 = argument2; this.metoda= function( argumenty) {opis metody //inne właściwości i inne metody
Teraz tworzymy egzemplarze (instancje) obiektu i przypisujemy do zmiennych referencji p1 i p2: var p1 = new Nazwa( argumenty aktualne); var p2 = new Nazwa( inne argumenty aktualne);
Przykład <PRE> <SCRIPT language="javascript"> //funkcja konstruktor function Pies(imie, rasa, kolor, plec) { this. imie= imie; this. rasa = rasa; this. kolor = kolor; this. plec= plec; this.glos ="HAUUUU"; //dla wszystkich psów ten sam this.dajglos = function() { document.writeln(this.glos); ; ; //tworzymy instancje właściwości przykładowa metoda var piesek1 = new Pies( "Misia", "Labrador", "czekoladowa", "suka" ); varpiesek2 = newpies( "Misiek", "Seter", "rudy", "pies" ); //możemy mieć dostęp do właściwości i metod document.writeln(piesek1.imie); // ->wypisze Misia piesek1.dajglos();// -> wykonanie metody - metoda wypisze "HAUUUU" //itd. </SCRIPT> </PRE>
Przykład metoda typu "get" <PRE> <SCRIPT language="javascript"> //funkcja konstruktor function Pies(imie, rasa, kolor, plec) { this. imie= imie; this. rasa = rasa; this. kolor = kolor; this. plec= plec; właściwości this.glos ="HAUUUU"; //dla wszystkich psów ten sam this.dajglos = function() { return this.glos; ; ; //tworzymy instancje var piesek1 = new Pies( "Misia","Labrador","czekoladowa", "suka"); varpiesek2 = newpies( "Misiek","Seter","rudy","pies"); //możemy mieć dostęp do właściwości i metod document.writeln(piesek1.imie); //-> Misia document.writeln(piesek1.dajglos());// -> instrukcja wypisuje wynik metody //itd. </SCRIPT> </PRE> metoda "get" (pobierz)
Przykład metoda typu "set" <PRE> <SCRIPT language="javascript"> //funkcja konstruktor function Pies(imie, rasa, plec) { this. imie= imie; this. rasa = rasa; this. kolor= "";//pustawartość this. plec= plec; this.glos ="HAUUUU"; //dla wszystkich psów ten sam this.ustawkolor = function(k ) { this.kolor = k; ; ; //tworzymy instancje var piesek1 = new Pies( "Misia", "Labrador", "czekoladowa", "suka" ); varpiesek2 = newpies( "Misiek", "Seter", "rudy", "pies" ); //możemy mieć dostęp do właściwości i metod document.writeln("kolor pieska 1:",piesek1.kolor); // -> jeszcze nie ma piesek1.ustawkolor("kremowa");// -> instrukcja nadaje wartość właściwości document.writeln("kolor pieska 1:",piesek1.kolor); // -> teraz kremowy </SCRIPT> </PRE> właściwości metoda "set" (ustaw)
Metody typu "get" zwracają jakąś wartość. W opisie metody jest zapis: return co_zwraca_metoda To co zwraca metoda można potem wypisać na ekranie: document.write(obiekt.metoda(argumenty)) lub użyć w wyrażeniach zgodnie z typem zwracanej wartości Metody typu get najczęściej zwracają właściwość obiektu - jest to tzw. hermetyzacja dostęp do właściwości powinien być tylko przy użyciu metod Metody typu "set" ustawiają wartość właściwości obiektu lub ją zmieniają nie maja return. Wykorzystuje się je jako osobną instrukcję w postaci: obiekt.metoda(argumenty)
function Auto (nr,nazwa) { //właściwości this.nr=nr; this.nazwa = nazwa; this.predkosc=0; //metody Inny przykład konstruktora obiektów this.podajnazwe = function(){ return this.nazwa; this.przyspiesz = function(dp){ this.predkosc=dp; this.zatrzymaj = function(){ this.predkosc=0; this.pokazpredkosc = function(){ return this.predkosc; this.wyswietl = function(){ var d=document.getelementbyid('ed'+this.nr); wybór elementu do wyświetlenia wartości d.innerhtml=this.podajnazwe()+' ma prędkość:'+this.pokazpredkosc();
Sposób 2 wykorzystuje tworzenie instancji <PRE> <SCRIPT language="javascript"> //funkcja konstruktor Pies2= function(imie, rasa, kolor, plec) { //definiowanie instancji obiektu tu uwaga na "interpunkcję"! varobiektpies= { imie: imie, rasa: rasa, kolor: kolor, plec: plec, glos:"hauuu", dajglos: function () { document.writeln(this.glos); ; //funkcja zwraca zdefiniowany obiekt return obiektpies; ;// KONIEC FUNKCJI //tworzenie instancji klasy var piesek3 = new Pies2( "Milka", "Spaniel", "czekoladowa", "suka" ); varpiesek4 = newpies2( "Reksio", "Dog", "czarny", "pies" ); //możemy mieć dostęp do właściwości i metod document.writeln(piesek3.imie); piesek3.dajglos(); //itd. </SCRIPT> </PRE>
W obu sposobach mamy ogólne definicje konstruktorów obiektu. Potem możemy tworzyć wiele egzemplarzy różniących się wartościami właściwości i wykonywać metody (akcje).
Ograniczenia dostępu do pól <PRE> <SCRIPT language=" JavaScript "> JakisObiekt= function (n1,n2) { w_pryw= n1; //właściwość prywatna (nie ma this) this.w_pub=n2; //właściwość publiczna this.podajnazwe1 = function () {return w_pryw; ; this.podajnazwe2 = function () {return this.w_pub; ; ; t = new JakisObiekt("prywatna","publiczna"); document.writeln("met1:",t.podajnazwe1());//tylko metoda podaje właściwość prywatną document.writeln("met2:",t.podajnazwe2());//metoda podaje też właściwość publiczną document.writeln("w_pryw:",t.w_pryw);//nie ma dostępu do prywatnej - undefined document.writeln("w_pub:",t.w_pub);// jest dostęp do właściwości publicznej </SCRIPT> </PRE>
Obiekty wewnętrzne W przypadku konieczności uwzględnienia pewnej liczby elementów o identycznym zestawie właściwości, wchodzących w skład definiowanego obiektu, możemy jedną z właściwości obiektu głównego zdefiniować jako pustą tablicę, a następnie wykorzystać odpowiednią metodę do wypełniania tablicy. Elementami takiej tablicy mogą także być obiekty (mamy wówczas możliwość zróżnicowania typów składowych obiektu). Tablica elementów może być dynamicznie wypełniana w programie (dowolna liczba jej składowych)
<PRE><SCRIPT language="javascript"> var Mechanizm= function(nr, typ) { this.nrr=nr; this.typr= typ; //pusta tablica this.dzwignie=[ ]; this.tworzdzwignie=function(nrdz, dldz) { //umieść obiekt wewnętrzny w podanej komórce tablicy this.dzwignie[nrdz-1]={ nrd: nrdz, dld: dldz, //koniec definicji konstruktora //tworzymy egzemplarz obiektu m1=new Mechanizm(1,'x25'); //tworzymy składowe obiektu m1.tworzdzwignie (1, 500); m1.tworzdzwignie (2,600); m1.tworzdzwignie (3,400); //wypisujemy nadane właściwości document.writeln("robot nr ",m1.nrr, " Typ:",m1.typR); document.writeln("ręce"); //elementy tablicy dzwignie for (k=0;k<m1.dzwignie.length;k++) { właściwości metoda document.writeln("nr dzwigni:", m1.dzwignie[k].nrd," długość dźwigni:",m1.dzwignie[k].dld); </SCRIPT></PRE>
Oddziaływanie wzajemne obiektów <HTML> <HEAD> </HEAD><BODY style="font-size:18px"> Oddzialywanie obiektów- gryzie ogon <PRE> <SCRIPT language="javascript"> var Kot=function(imie, ogon) { this.imie=imie; this.ogon=ogon; this.ugryz=function(ob){//argumentem metody jest inny obiekt ob.ogon-=5; kot1= new Kot ("Maciuś",20); kot2= new Kot ("Misiek", 20); document.writeln(kot1.imie," ma ogon",kot1.ogon); document.writeln(kot2.imie," ma ogon",kot2.ogon); document.writeln(kot2.imie," gryzie", kot1.imie); kot2.ugryz(kot1);//kot2 gryzie kota1 document.writeln(kot1.imie," ma teraz ogon",kot1.ogon); document.writeln(kot1.imie," gryzie", kot2.imie); kot1.ugryz(kot2);//kot1 gryzie kota2 document.writeln(kot2.imie," ma teraz ogon",kot2.ogon); </SCRIPT> </PRE> </BODY></HTML>
Dziedziczenie obiektów Prototyp (prototype) to specjalna właściwość obiektowa, którą posiada każdy obiekt. Prototyp można wykorzystać do nadania dowolnej wartości (obiektowej). Prototyp oznacza obiekt, który niejawnie udostępnia swoje właściwości innym obiektom. W języku JavaScript prototyp jest tworzony oraz udostępniany każdej powstającej instancji wybranej klasy. Gdy użytkownik pragnie odczytać właściwość, która nie jest obecna w danej instancji, jest ona wyszukiwana w jej prototypie. Wykorzystamy prototyp do przepisania całego obiektu nadrzędnego do obiektu podrzędnego i utworzenia nowych właściwości obiektu potomnego.
<PRE><SCRIPT language="javascript"> //konstruktor przodka var Zwierze = function(wiek) { this.nazwaprzodka ='zwierzę'; this.wiek = wiek; //konstruktor potomka var Kot = function(imie, siersc) { this.nazwaklasy='kot'; this.nazwa = imie; this.nogi = 4; this.siersc= siersc; //przepisanie do prototypu właściwości obiektu Zwierze( ) Kot.prototype = new Zwierze(4) //nowa właściwość prototypu Kot.prototype.glos = 'Miauuu'; //tworzymy obiekt k= newkot("maciek", "ruda"); //wyświetlamy jego właściwości document.writeln("utworzyliśmy obiekt typu:",k.nazwaklasy) ;// wyświetli: Kot document.writeln("przodek:",k.nazwaprzodka); // wyświetli: zwierzę document.writeln("nazwa:",k.nazwa) ;// wyświetli: Maciek document.writeln("nogi:",k.nogi) ;// wyświetli: 4 document.writeln("głos:",k.glos) ;// wyszukane w prototypie- wyświetli: Miauuu document.writeln("wiek:",k.wiek) ;// wyświetli: 1 document.writeln("sierść:",k.siersc) ;// wyświetli: ruda </SCRIPT></PRE>
<PRE><SCRIPT language="javascript"> //konstruktor przodka urzelektr = function(napiecie, producent) { this.nazwa ='Urządzenie elektryczne'; this.napiecie = napiecie; this.producent = producent; //konstruktor potomka Lodowka = function(producent, temp_min) { this.nazwaklasy='lodówka'; this.temp_min=temp_min; //przepisanie do prototypu właściwości obiektu urzelektr( ) Lodowka.prototype = new urzelektr(230, "Bosch") //możemy dodać nową właściwość prototypu Lodowka.prototype.podtyp= "AGD" ; //tworzymy obiekt k= new Lodowka( -10); //wyświetlamy jego właściwości document.writeln("utworzyliśmy obiekt typu:", k.nazwaklasy) ;// wyświetli: Lodówka document.writeln("przodek:", k.nazwa); // wyświetli: Urządzenie elektryczne document.writeln("producent", k.producent) ;// wyświetli: Bosch document.writeln("podtyp:",k.podtyp) ;// wyszukane w prototypie- wyświetli: AGD </SCRIPT></PRE>
UWAGA: Przy tworzeniu hierarchii obiektów należy uważnie i sensownie projektować właściwości i metody. W powyższym przykładzie producent i napięcie są właściwościami urzelektr() (każde urządzenie elektryczne producenta, napięcie), zaś temperatura minimalna, podtyp to już właściwości lodówki (nie każde urządzenie ma podtyp czy temperaturę jako ważną właściwość).
Polimorfizm(wielopostaciowość) Przedefiniowanie metody obiektu nadrzędnego w obiekcie potomnym nosi nazwę polimorfizmu (wielopostaciowości).
<PRE><SCRIPT language="javascript"> // konstruktor obiektu Auto( ) function Auto(x) { this.nazwa = x; this.podajnazwe = function( ){ document.writeln("auto:", this.nazwa); // konstruktor obiektu AutoSuper function AutoSuper(n) { //przepisanie do prototypu cech obiektu Auto( ) this.prototype = new Auto(n); //nowa właściwość this.prototype.turbo=" Ma turbo"; //można nadpisać (przedefiniować) metodę podajnazwe AutoSuper.prototype.podajNazwe = function( ) { document.writeln("auto-super:",this.prototype.nazwa," turbo:", this.prototype.turbo); ;
//tworzymy instancję obiektu Auto( ) var a1 = new Auto("MacLaren"); //wywołujemy funkcje utworzonego obiektu a1.podajnazwe( ); // sprawdzamy istnienie właściwości turbo if(a1.turbo==undefined) document.writeln("to auto nie ma turbo"); //inicjalizujemy obiekt potomny var a2 = new AutoSuper("MacLaren"); // sprawdzamy przedefiniowanie metody podajnazwe() a2.podajnazwe( ); </SCRIPT> Teraz mamy: Definicję obiektu Auto() z metodą podajnazwe() Definicję obiektu potomnego AutoSuper() posiadającą: o dodatkową właściwość turbo o przedefiniowaną metodę podajnazwe().