Iltaa!
Onnistuuko JavaScriptissä periytys siten, että luokat/metodit on sisäkkäin? Tyyliä tämä:
function a(){ a.prototype.b = function(){ //Do something... b.prototype.c = function(){ //Do something... } } }
Siis tarkoitatko:
function a(){ this.b = function(){ //Do something... this.c = function(){ //Do something... } } }
Vai enkö nyt ymmärtänyt jotain?
Joku ei nyt taida ymmärtää, mitä periminen olio-ohjelmoinnissa tarkoittaa.
En yhtään ymmärrä, mitä tarkoittaa ”että luokat/metodit on sisäkkäin”. Tai no näenhän koodisi, mutta ei tuossa ole mitään järkeä. Miksi muokkaisit prototyyppiä jossain funktion sisällä? Mikä on tuo jälkimmäinen b, jonka prototyyppiä muokkaat? Mitä oikein odotat tapahtuvan? Pyritkö ehkä jotenkin tuohon Grezin esittämään tulokseen?
Prototyyppiketjussa voi kyllä olla useampikin prototyyppi, mutta ketju pitää koota oikein, eikä asia liity mitenkään funktioiden sijoitteluun koodissa. (Lue vaikka MDN: JavaScript: Inheritance and the prototype chain.) Tässä on yksi toimiva tapa. En paljon koodaa JS:llä, joten en takaa ratkaisun ehdotonta tyylikkyyttä.
function A(p1) { print("new A: " + p1); } // A.prototype = Object.create(Object.prototype); // A.prototype.constructor = A; A.prototype.fa = function() { print("instanceof A: " + (this instanceof A)); } function B(p1, p2) { print("new B: " + [p1, p2]); A.apply(this, [p1]); } B.prototype = Object.create(A.prototype); B.prototype.constructor = B; B.prototype.fb = function() { print("instanceof B: " + (this instanceof B)); } function C(p1, p2, p3) { print("new C: " + [p1, p2, p3]); B.apply(this, [p1, p2]); } C.prototype = Object.create(B.prototype); C.prototype.constructor = C; C.prototype.fc = function() { print("instanceof C: " + (this instanceof C)); } var x = new C(1, 2, 3); x.fa(); x.fb(); x.fc();
En itsekään ole kärryillä mitä yrität ajaa takaa, mutta jos yrität jonkinsortin namespacea rakennella prototypelläsi, suosittelen vaikka seuraavaa mallia:
var myNamespace = { models: { product: function (price) { this.price = price; this.getPrice = function() { return this.price; }; }, person: function(gender,birthYear) { this.gender = gender; this.getGender = function() { return this.gender; } this.birthYear = birthYear; this.getBirthYear = function() { return this.birthYear; } } }, logic: { calculateVat: function (product) { return product.getPrice() * 1.23; }, calculateAge: function(person) { return new Date().getFullYear() - person.getBirthYear(); } } } $(document).ready(function() { var product = new myNamespace.models.product(200); alert(myNamespace.logic.calculateVat(product)); var person = new myNamespace.models.person("male",1982); alert(myNamespace.logic.calculateAge(person)); });
JavaScriptissä pystyy esittelemään protyyppejä tavalla, jonka näytin:
AObj.prototype.BObj = function(){}
Ja se(esitteleminen) onnistuu tuolla funktion sisällä, mutta se mitä ajan takaa, vaikka taisin kysyä vähän eri asiaa, on se, että kuinka vastaavalla tavalla sitten esitellään CObj, jonka prototyyppi on siis BObj?
Tuo sisäkkäin ajettelu oli lähinnä aivopieru, eikä välttämättä järkevää.
dartvaneri kirjoitti:
JavaScriptissä pystyy esittelemään protyyppejä – – esitellään CObj, jonka prototyyppi on siis BObj
... mitä? Nyt kyllä vaikuttaa, että olet jotenkin pihalla JavaScriptin oliojärjestelmästä. Sijoitatpa kohtaan AObj.prototype.BObj funktion milloin hyvänsä, AObj:lla ja BObj:lla ei ole mitään yhteyttä: kumpikaan ei ole toisen prototyyppi, vaan ainoastaan AObj-funktiolla luoduille olioille tulee jäsenfunktio nimeltä BObj.
Ajatellaan nyt, että A on konstruktorifunktio. Tällöin A:n prototyyppiin lisättävät funktiot eivät kuulu A-funktion sisään vaan sen jälkeen. Prototyypin eräs ideahan on nimenomaan se, että yhteiset jäsenet luotaisiin vain kerran. Jos sijoitus tehdään A-funktion sisällä, arvo muuttuu joka kerta.
Tämä koodi demonstroi sijoituspaikan epäloogisuutta ja siitä seuraavaa ongelmaa:
var j = 0; function A() { var i = ++j; A.prototype.x = function() { return i; } } var a = new A(); var ax = a.x; var b = new A(); print("ax == a.x ? => ", (ax == a.x)); // false, a.x on muuttunut! print("b.x == a.x ? => ", (b.x == a.x)); // true print("ax() == " + ax()); // 1 print("a.x() == " + a.x()); // 2 print("b.x() == " + b.x()); // 2
Jos haluat luoda useamman eri "luokan", katso edellistä koodiani: Pitää tehdä monta funktiota ja laittaa niille sopivat prototyypit. Perintää varten tarvitaan prototyypin prototyyppi, jonka saa aikaan luomalla uuden prototyypin vanhasta prototyypistä funktiolla Object.create. (Myös new toimii, mutta siinä suoritetaan turhaan "kantaluokan" muodostin, jolla voi olla myös ei-toivottuja sivuvaikutuksia.)
Aihe on jo aika vanha, joten et voi enää vastata siihen.