Objektorientierung in JavaScript/Datenkapselung, Vererbung, Polymorphie/Datenkapselung

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Javascript</language>
Datenkapselung bedeutet, dass ein Objekt seine Attribute nach außen hin versteckt (information hiding) und sie so vor ungeregeltem Zugriff schützt. Es hat das alleinige Recht, auf seine Daten zuzugreifen und sie zu lesen oder zu ändern. Möchten andere Objekte Zugriff auf die Daten erhalten, müssen sie dies über definierte Schnittstellen tun.
[[Bild:Flogerlinghoff_Datenkapselung1.JPG]]

In JavaScript kann auf Variablen, die im Konstruktor nicht mit dem Schlüsselwort ''this'' gekennzeichnet wurden, nicht von außen zugegriffen werden.

<code id="54jhin213jn1">
function Person(name) {
  var name = name;
  this.getPersonsName = function() {
    return name;
  }
}
</code>
<run id="54jhin213jn2">
var peter = new Person("Peter");
typeof(peter.name);
</run>
<run id="54jhin213jn3">
var Emma = new Person("Emma");
Emma.getPersonsName();
</run>

Methoden, die in der Konstruktorfunktion der Klasse liegen, haben die Möglichkeit, auf die privaten Variablen im Konstruktor zuzugreifen. Man nennt sie deshalb auch priviligierte Methoden.
Methoden, die über <tt>ClassName.prototype.method</tt> definiert werden, können das nicht.
<code id="5427190802042016">
function Haustier(name) {
  var name = name;
}
Haustier.prototype.getHaustiersName = function() {
  return this.name;
};
</code>
<run id="5426191002042016">
var urmel = new Haustier("Urmel");
urmel.getHaustiersName();
</run>

==Aufgaben==
Bei der Klasse ''Buch'' sollen die Attribute ''autor'' und ''seitenanzahl'' gekapselt werden. Der Zugriff soll über die Methoden ''getAutor'' und ''getSeitenanzahl'' möglich sein.

<code id="54uhiqwu891">
function Buch (titel, autor, verlag, seitenanzahl) {
  ...
}
</code>
<check>
var cleanCode = new Buch("Clean Code", "Uncle Bob", "mitp-Verlag", 480);
return (typeof cleanCode.seitenanzahl == "undefined" && typeof cleanCode.autor == "undefined" && cleanCode.getSeitenanzahl() == 480 && cleanCode.getAutor() == "Uncle Bob");
</check>
<run id="56fac5b8a63d7">
var cleanCode = new Buch("Clean Code", "Uncle Bob", "mitp-Verlag", 480);
</run>

Durch Datenkapselung kann erreicht werden, dass zwei Eigenschaften nur zusammen geändert werden dürfen. 
Wenn die elektrische Kraft in einem Radialfeld gleich bleiben soll, aber eine der beiden Ladungen geändert wird, muss entweder der Abstand der Ladungen zueinander oder der Betrag der zweiten Ladung auch geändert werden (siehe [https://de.wikipedia.org/wiki/Coulombsches_Gesetz Coulombsches Gesetz]).
Implementiere die Methoden <tt>getQ1()</tt>, <tt>getQ2()/tt>, <tt>getR()/tt>, <tt>getF()</tt>, <tt>setQ1(newValue)</tt> und <tt>setQ2(newValue)</tt>. Wenn eine Ladung geändert wird, soll die andere automatisch angepasst werden, sodass der Betrag der Kraft gleich bleibt.
<code id="5427195102042016">
function Radialfeld(q1, q2, r) {
  var q1 = q1;
  var q2 = q2;
  var r = r;

  this.getQ1 = function() { return q1; };
  this.getQ2 = function() { return q2; };
  this.getR  = function() { return r; };
  this.getF  = function() {
    return (1 / (4*Math.PI*(8.854*Math.pow(10, -12)))) * ((this.getQ1() * this.getQ2()) / Math.pow(this.getR(), 2));
  };

  this.setQ1 = function(newV) {
    q2 = this.getQ2() * this.getQ1() / newV;;
    q1 = newV;
  };
  this.setQ2 = function(newV) {
    q1 = this.getQ1() * this.getQ2() / newV;
    q2 = newV;
  };
}
</code>
Zur Berechnung der Kraft wird Math.PI verwendet. e0 ist mit 8.854*10^(-12) definiert.
<check>
Radialfeld rf = new Radialfeld(0.08, 0.02, 0.1);
var checkGetF = rf.getF() == (1 / (4*Math.PI*(8.854*Math.pow(10, -12)))) * ((rf.getQ1() * rf.getQ2()) / Math.pow(rf.getR, 2));
var oldF = rf.getF();
rf.setQ1(0.05);
var checkSetQ1 = this.getQ2 == 0.032;
rf.setQ2(0.04);
var checkSetQ2 = this.getQ1 == 0.04;
return checkGetF && checkSetQ1 && checkSetQ2;
</check>
<run id="5426200802042016">
Radialfeld rf = new Radialfeld(0.08, 0.02, 0.1);
rf.setQ1(0.05);
</run>