Napsal jsem článek o porozumění prototypům a dědičnosti v JavaScriptu pro DigitalOcean, ve kterém jsem vysvětlil, jak používat funkce konstruktoru a vytvářet nové objekty, které z nich dědí. Myslel jsem, že by bylo zajímavé přepsat úplně stejný kód jako třída JavaScript ES6 a třída PHP a získat stejný výstup. Zde je tedy srovnání stejného vzoru a výstupu v ES5, ES6 a PHP vedle sebe.
Pomocí tříd ES6 vysvětlím, co vzor dělá.
Vytvoříme třídu (návrh objektu) a rozšíříme třídu (dědičnost). Jako příklad používám třídy postav RPG.
// Creating a class
class Hero {}
// Extending a class
class Warrior extends Hero {}
Přidám constructor()
funkce pro přiřazení dvou parametrů třídě.
class Hero {
// Assigning parameters with constructor
constructor(name, level) {
this.name = name
this.level = level
}
}
// Extending a class
class Warrior extends Hero {}
Přidám také metodu.
class Hero {
constructor(name, level) {
this.name = name
this.level = level
}
// Adding a method
greet() {
return `${this.name} says hello.`
}
}
class Warrior extends Hero {}
Nyní upravíme zděděnou třídu a přidáme nový parametr. Používáme super()
pro přístup k parametrům od rodiče – jinak by k nim zděděná třída nemohla přistupovat a pracovat s nimi.
class Hero { ... }
class Warrior extends Hero {
// Adding a constructor
constructor(name, level, weapon) {
// Access and call function from parent
super(name, level);
this.weapon = weapon;
}
}
Nakonec do rozšířené třídy přidáme metodu.
class Hero {}
class Warrior extends Hero {
constructor(name, level, weapon) {
super(name, level)
this.weapon = weapon
}
// Adding a method
attack() {
return `${this.name} attacks with the ${this.weapon}.`
}
}
Nyní, když jsou plány třídy a rozšířené třídy připraveny, můžeme vytvořit novou postavu, která má přístup k parametrům a metodám původní třídy a rozšířené třídy.
// Initialize individual character instance
const hero1 = new Warrior('Bjorn', 1, 'axe')
console.log(hero1.attack())
console.log(hero1.greet())
Úplný kód a výstup pro funkce a třídy konstruktoru JS a třídy PHP jsou uvedeny níže.
Třída JavaScript ES6
class
klíčové slovo bylo zavedeno s ES6. Třídy jsou postaveny na prototypech v JavaScriptu.
class Hero {
constructor(name, level) {
this.name = name
this.level = level
}
greet() {
return `${this.name} says hello.`
}
}
class Warrior extends Hero {
constructor(name, level, weapon) {
// Access and call function from parent
super(name, level)
this.weapon = weapon
}
attack() {
return `${this.name} attacks with the ${this.weapon}.`
}
}
// Initialize individual character instance
const hero1 = new Warrior('Bjorn', 1, 'axe')
console.log(hero1.attack())
console.log(hero1.greet())
Výstup
Bjorn attacks with the axe.
Bjorn says hello.
Funkce konstruktoru JavaScript ES5
Funkce konstruktoru JavaScriptu byly vytvořeny jako pokus přenést funkčnost tradičního objektově orientovaného návrhu tříd do jazyka JavaScript.
constructor-functions-es5.jsfunction Hero(name, level) {
this.name = name
this.level = level
}
function Warrior(name, level, weapon) {
// Access and call function from parent
Hero.call(this, name, level)
this.weapon = weapon
}
// Link prototypes and add prototype methods
Warrior.prototype = Object.create(Hero.prototype)
Hero.prototype.greet = function () {
return this.name + ' says hello.'
}
Warrior.prototype.attack = function () {
return this.name + ' attacks with the ' + this.weapon + '.'
}
// Initialize individual character instance
const hero1 = new Warrior('Bjorn', 1, 'axe')
console.log(hero1.attack())
console.log(hero1.greet())
Výstup
Bjorn attacks with the axe.
Bjorn says hello.
Třída PHP
Zde je jednoduchý příklad konstruktoru třídy PHP.
class-php.php
<?php
class Hero {
public function __construct($name, $level) {
$this->name = $name;
$this->level = $level;
}
public function greet() {
return "{$this->name} says hello.";
}
}
class Warrior extends Hero {
public function __construct($name, $level, $weapon) {
// Access and call function from parent
parent::__construct($name, $level, $weapon);
$this->weapon = $weapon;
}
public function attack() {
return "{$this->name} attacks with the {$this->weapon}.";
}
}
// Initialize individual character instances
$hero1 = new Warrior('Bjorn', 1, 'axe');
echo $hero1->attack();
echo $hero1->greet();
Výstup
Bjorn attacks with the axe.
Bjorn says hello.
Samozřejmě, třídy JavaScriptu jsou „syntaktický cukr“ (fuj) nad prototypy, což znamená, že třídy ES6 ve skutečnosti neběží na objektově orientovaném modelu dědičnosti. Populární knihovny jako React však mají tendenci třídy hodně využívat, takže je dobré je znát. Příklad PHP ukazuje skutečnou třídu z tradičního objektově orientovaného systému, ale s tímto jednoduchým příkladem můžeme získat stejný výstup v obou směrech.
Osobně dávám přednost syntaktické soli.