• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Oop

tröröö

New member
Hi :)

Ich hab jetzt mal mit folgendem Script herumexperimentiert:

HTML:
<!doctype html>
<html>
   <head>
      <meta charset="UTF-8">
      <script language="JavaScript">
         "use strict";

         // Shape - superclass
         function Shape() {
            // private:
               var z = 0;
            
               function f()
               {
                  return 2;
               }
               
            // public:
               this.x = 0;
               this.y = 0;

               // superclass method
               this.move = function(_x, _y, _z) {
                  this.x += _x + f();
                  this.y += _y + f();
                  z      += _z + f();
                  
                  console.info("Shape moved.");
               };
               
               this.getZ = function() {
                  return z;
               };
         }

         // Rectangle - subclass
         function Rectangle() {
            Shape.call(this); // call super constructor.
            
            // public:
               this.u = 0;
               
               this.move2 = function(_x, _y) {
                  this.u += 100;
                  this.x += _x;
                  this.y += _y;

                  console.info("Shape moved 2.");
               };
         }

         // subclass extends superclass
         Rectangle.prototype = Object.create(Shape.prototype);
         Rectangle.prototype.constructor = Rectangle;

         var rect0 = new Rectangle();
         var rect1 = new Rectangle();

         rect0 instanceof Rectangle // true
         rect0 instanceof Shape     // true

         rect1.move(1, 1, 1); // Outputs, "Shape moved."

         alert(rect0.x); // 0
         alert(rect1.x); // 3
         
         alert(rect0.getZ()); // 0
         alert(rect1.getZ()); // 3
         
         rect1.move2(8, 8); // Outputs, "Shape moved 2."
         
         alert(rect0.x); // 0
         alert(rect1.x); // 11
         alert(rect1.u); // 100
         
         alert(rect1.z);   // undefined
         alert(rect1.f()); // Error: is not a function
      </script>
   </head>
</html>

Scheint alles super zu funktionieren!! :) Man kann scheinbar zwischen privaten und öffentlichen Eigenschaften/Methoden unterscheide.

Ist das jetzt die offizielle Vorgehensweise, wie man in JavaScript objektorientiert programmiert?
 
Ich hab die Links mal durchgeblättert, aber da scheint auf meine Variante gar nicht eingegangen zu werden.
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
(Die getter/setter-Methoden scheinen dort auch überall zu fehlen ... nur so nebenbei erwähnt :) )
 

Also was der da für einen Krampf schreibt... da ist einiges falsch und vieles nicht guter Stil (z.B. schon mal angefangen mit dem Code-Stil... inkonsistent und potentiell gefährlich).

Ich bin ja der Meinung, dass man in JS einfach nicht in klassischen OOP-Prinzipien (wie man sie von Java kennt) denken sollte - man denkt in Java ja auch nicht prozedural, obwohl man solchen Java-Code erzeugen kann: einfach alle Methoden static machen und in der main() keine Objekt erzeugen.

OOP in JS ist nämlich ganz einfach - es gibt nur vier Dinge, die man verstehen muss:
  1. Scope - regelt die Sichtbarkeit von Variablen
  2. Funktionskontext - ist einfach das, was in this gespeichert ist. Das ist entweder der erste Parameter der .call()- bzw. .apply()-Methodenaufrufe von Funktionen oder das Objekt, in dem die Funktion als Eigenschaft aufgerufen wurde (obj.method()).
  3. der new-Operator - erzeugt ein neues Objekt mit dem Prototyp der übergebenen Funktion, ruft die Funktion im Kontext des erzeugten Objektes auf und gibt dieses Objekt zurück, wenn die Funktion keinen anderen Rückgabewert hat.
  4. die Prototype-Chain - ist für Einsteiger am schwersten zu verstehen, aber im Grunde genommen ist es eine Lookup-Regel: schau' zuerst, ob das Objekt eine gewisse Eigenschaft hat. Wenn das nicht der Fall ist, gehe in den Prototyp des Objektes und starte die Regel von dort aus neu.

OK - es gibt noch ein paar andere Dinge, die man über JS wissen muss, z.B. dass Funktionen First-Class-Citizen sind - es somit keinerlei Unterschied zwischen einer Eigenschaft und einer Methode gibt.

Somit gibt es keine "offizielle" Vorgehensweise für OOP in JS... egal, was du in JS machst, es ist immer OOP, da alles ein Objekt ist.
Wenn du in JS Java abbilden willst, kannst du das gerne machen - ist nur langsamer und beschränkt dich.

PS: obj.method() ist eigentlich syntaktischer Zucker und kann als obj.method.call(obj) interpretiert werden.
PPS: wenn du ECMA 262 5th Edition voraussetzten willst, was du durch dir Verwendung von Object.create() tust, kannst du dir getter/setter-Methoden in der klassischen Form komplett sparen:
Code:
var obj = Object.create(null, {
	a: {
		set: function(a){
			alert(a);
		},
		get: function(){
			return "hallo";
		}
	}
});
alert(obj.a);
obj.a = 2;
alert(obj.a);
- aber wie man an dem Beispiel wunderbar erkennen kann, kann man Code damit so gestalten, dass er überhaupt nicht mehr nachvollziehbar ist... für "normale" Setter und Getter ist das aber perfekt geeignet.
 
Somit gibt es keine "offizielle" Vorgehensweise für OOP in JS... egal, was du in JS machst, es ist immer OOP, da alles ein Objekt ist.
Ja, die Fragestellung war etwas unpräzise.

Nehmen wir mal PHP. Dort kann man auch Objekte erzeugen, ohne dass man eine Klasse definieren muss. Was in JavaScript "new Object" ist, entspricht in PHP dem "new stdClass". Mir ist schon klar, dass man auch so objektorientiert programmieren kann, aber das meinte ich nicht.

Ich meinte schon ein Programmieren mit Klassen - bzw. mit etwas klassenähnlichen. Etwas, womit man auch unterscheiden kann zwischen privaten und öffentlichen Daten. Und wo man auch erben kann. Und zwar richtig erben. In JavaScript ist das ja nicht unbedingt eine Selbstverständlichkeit aufgrund des Prototyping. Da kann schon mal die Instanz einer Klasse eine Eigenschaft einer anderen Instanz der gleichen Klasse verändern, obwohl man eigentlich gar kein statisches Verhalten programmieren wollte.

Bei meinem Script habe ich den Eindruck, dass es dem Programmieren von Klassen und Objekten, die zwischen private und public unterscheiden können und wo auch ein sauberes Vererben ohne irgendwelche seltsamen Tricks doch schon recht nahe kommt.

Darum frage ich mal anders: Kommt mein Script in dieser Form dem am nächsten, wie man typischerweise in objektorierten Programmiersprachen wie PHP oder Java programmiert? Oder gibt es in JavaScript noch eine andere, bessere Lösung?
 
Ich habe jetzt noch einen ganz neuen Programmierstil gefunden, den ich bis jetzt noch gar nicht kannte. Und zwar wird mit prototype gearbeitet, jedoch steckt das noch in einer Funktion.

Gefunden habe ich diesen Stil nicht auf einer JavaScript-Seite, sondern auf einer TypeScript-Seite: TypeScript - Playground

Hat dieser Stil irgendwie einen bestimmten Namen?

Und wie arbeitet man hier mit Vererbung?

EDIT: Also bei der ersten Frage hat mir schon wer geholfen :) Das nennt sich scheinbar http://briancray.com/posts/javascript-module-pattern
 
Zuletzt bearbeitet:
Kann man in Klassen, die mittels module-pattern definiert wurden, auch private Eigenschaften definieren? Ich versuch das jetzt schon einige Zeit lang, aber das klappt nicht.

Hier mein Testscript:
HTML:
<!doctype html>
<html>
   <head>
      <meta charset="UTF-8">
      <script language="JavaScript">
         "use strict";
         
         var module = (
            function () {
               // private prop:
                  var p0 = 0;
                  var p1;
                  var p2;
                  var p3;
                  var p4;
                  
               // private meth:
                  function f() {
                     return 7;
                  }
               
               // Konstruktor:
                  var module = function(c, p) {
                     p1 = 1;
                     p4 = c;
                     this.p5 = p;
                     this.p7 = f();
                  };
                  module.prototype.constructor = module;
                  
               // public prop:
                  module.prototype.p5;
                  module.prototype.p6 = 6;
                  module.prototype.p7;
                  
               // public meth:
                  module.prototype.getP0 = function() {
                     return p0; // 0
                  };
                  module.prototype.getP1 = function() {
                     return p1; // 1
                  };
                  module.prototype.setP2 = function(p) {
                     p2 = p;
                  };
                  module.prototype.getP2 = function() {
                     return p2; // 2
                  };
                  module.prototype.setP3 = function() {
                     p3 = this.p6 / 2;
                  };
                  module.prototype.getP3 = function() {
                     return p3; // 3
                  };
                  module.prototype.getP4 = function() {
                     return p4; 
                  };
                
               return module;
            }
         )();

         var oM0 = new module(4, 5);
         var oM1 = new module(400, 500);
         
         oM0.setP2(2);
         oM0.setP3();
         console.log(oM0.getP0()); // 0
         console.log(oM0.getP1()); // 1
         console.log(oM0.getP2()); // 2
         console.log(oM0.getP3()); // 3
         console.log(oM0.getP4()); // hier sollte 4 stehen, kommt jedoch 400 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         console.log(oM0.p5);      // 5
         console.log(oM0.p6);      // 6
         console.log(oM0.p7);      // 7
         
         console.log(oM1.getP4()); // 400
         console.log(oM1.p5);      // 500
      </script>
   </head>
</html>
 
Den Begriff module-pattern kannte ich noch gar nicht, obwohl ich das für meine Module immer verwende - für mich ist das einfach nur Scope...

Bei deinem Problem mit der "privaten" Eigenschaft sieht man mal wieder, dass das Konzept in JS einfach nicht gut passt, da es jetzt zwei verschiedene Arten von "privat" gibt: die eine, die du jetzt hast (was im Grunde genommen eine statische Eigenschaft repräsentiert) und das, was du gerne hättest (das musst du genau so lösen, wie du es im erste Beispiel gemacht hast: eine lokale Variable und ihre Setter-/Getterfunktion im Konstruktor).

PS: in deinem letzten Beispiel ist die Funktion setP3 nicht gut. Die Rechnung sollte in getP3 ausgeführt werden.
 
EDIT

das musst du genau so lösen, wie du es im erste Beispiel gemacht hast
Neuer Versuch:
HTML:
<!doctype html>
<html>
   <head>
      <meta charset="UTF-8">
      <script>
         "use strict";
         
         var module = (
            function () {
               // private static prop:
                  var p0 = 1;
               
               // Konstruktor:
                  var module = function() {
                     // private prop:
                        var xxx = 200;
                        this.getXXX = function() {
                           return xxx;
                        }
                  };
                  module.prototype.constructor = module;

               // public meth:
                  module.prototype.getP0 = function() {
                     return p0 + this.getXXX(); // 0
                  };
                
               return module;
            }
         )();

         var oM = new module();
         console.log(oM.getP0());
      </script>
   </head>
</html>
Meinst du das so?
 
Zuletzt bearbeitet:
Äh... man kann immer zwischen "statischen" und "normlen" Eigenschaften unterscheiden... wobei du nirgends statischen Eigenschaften eingebaut hast, sondern einfach nur lokale Variablen. Und durch das module-pattern hast du einfach einen zusätzlichen Scope, in den du lokale Variablen reinpacken kannst.

Ich meinte, dass sich der Aufwand für "private" Eigenschaften (es wiederstrebt mir extrem, das du schreiben, weil es das in JS einfach nicht gibt!) nicht lohnt. Das Sicherheitskonzept von JS ist einfach anders aufgebaut: wenn ich auf ein Objekt zugreifen kann, kann ich auch damit machen, was ich will. Z.B. kann ich getXXX mit einer eigenen Funktion überschreiben...
 
Zurück
Oben