Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: JavaScript: Periytys

dartvaneri [17.03.2015 21:30:41]

#

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...
        }
    }
}

Grez [17.03.2015 21:40:13]

#

Siis tarkoitatko:

function a(){
    this.b = function(){
        //Do something...
        this.c = function(){
            //Do something...
        }
    }
}

Vai enkö nyt ymmärtänyt jotain?

The Alchemist [17.03.2015 22:25:27]

#

Joku ei nyt taida ymmärtää, mitä periminen olio-ohjelmoinnissa tarkoittaa.

Metabolix [18.03.2015 00:06:07]

#

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();

groovyb [18.03.2015 01:41:57]

#

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));

});

dartvaneri [18.03.2015 15:17:40]

#

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ää.

Metabolix [18.03.2015 16:11:24]

#

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.)

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta