[PYTHON] Die Geschichte, dass Vererbungsverhalten in jeder Sprache sehr unterschiedlich ist

Einführung

Dieser Artikel ist eine Zusammenstellung der Ergebnisse meiner Forschung darüber, welche Werte tatsächlich ausgegeben werden, indem die Klassenvererbung auf ähnliche Weise in verschiedenen Sprachen geschrieben wird. Manchmal habe ich hart an Hello World gearbeitet und gedacht, dass es eine solche Grammatik auch in einer bekannten Sprache gibt.

Wer würde davon profitieren, wenn es schwierig wäre, sie zusammenzustellen? Ich werde es jedoch denen überlassen, die sich für das Gleiche interessieren. Nein, möglicherweise gibt es neue Entdeckungen. Bitte lesen Sie diese vorerst. Es könnte ein überraschend interessantes Ergebnis gewesen sein.

Sprache geprüft

--Statische Eingabe

In der Umfrage verwendeter Code

Eine untergeordnete Klasse erbt eine übergeordnete Klasse. Die übergeordneten und untergeordneten Klassen haben Instanzvariablen mit demselben Namen. (Keine Klassenvariable) Die übergeordnete Klasse verfügt über eine Methode, mit der Sie Instanzvariablen an die Konsole ausgeben können.

Zur Laufzeit ruft die untergeordnete Klasseninstanz die geerbte übergeordnete Methode auf. Die Geschichte lautet nun ** Welche Instanzvariable wird ausgegeben, Eltern oder Kind? ** …….

Wenn Sie es in JS-Code (ES6 oder höher) schreiben, den wahrscheinlich viele Leute lesen können, ist es ein solcher Code.

class SuperClass {
  constructor() {
    //* In JS werden Instanzvariablen zur Laufzeit definiert. Schreiben Sie sie daher in den Konstruktor.
    this.instanceVariable = "SuperClass" //Unterschiedliche Werte mit demselben Namen
  }

  superClassMethod() {
    console.log(this.instanceVariable)
  }
}

class SubClass extends SuperClass {
  constructor() {
    super()
    this.instanceVariable = "SubClass" //Unterschiedliche Werte mit demselben Namen
  }
}

const sub = new SubClass() //Intensivierung der Kinderklasse
sub.superClassMethod() //Rufen Sie die geerbte übergeordnete Klassenmethode auf

Stellen Sie sich vor, welche Werte in der Sprache ausgegeben werden, die Sie normalerweise verwenden. Es ist ein gelegentlicher Schreibstil (gut oder schlecht), sodass Sie vielleicht wissen, was Sie können. Wenn Sie jedoch wissen, wie es in anderen Sprachen funktioniert, kann es eines Tages nützlich sein, wenn Sie ein anderes Unternehmen oder ein anderes Projekt betreten oder wenn Sie daran interessiert sind, in einer anderen Sprache zu beginnen.

Dieses Mal betrachte ich nicht nur die Instanzvariablen, sondern auch, was passiert, wenn Sie "SuperClass" mit einer Methode zurückgeben (eine Methode einer Instanz, die keine Klassenmethode ist). In diesem Fall haben die übergeordnete Klasse und die untergeordnete Klasse eine Methode mit demselben Namen, und die Methode der übergeordneten Klasse nennt sie ....

Sie können herausfinden, welchen Code Sie geschrieben und nachgeschlagen haben

Code anzeigen (Hoge-Sprache)
class Hoge {}

Da das detaillierte Faltelement so platziert ist, können Sie den Code darin lesen, indem Sie darauf klicken, um ihn zu öffnen. Es ist ein hübscher WET-Code, der im Prinzip Kopieren und Einfügen verwendet, um leichter zu sehen, was Sie tun, aber werfen Sie Masakari nicht, weil es beabsichtigt ist.

Diesmal ist es soweit

Wie Sie wissen, haben verschiedene Programmiersprachen unterschiedliche Grammatiken und Bewertungsmethoden. Ich denke, die Punkte, die diesmal die Ergebnisse verändern werden, sind folgende.

  • Existiert der Zugriffsmodifikator? Auch was für Dinge gibt es
  • Ist es überhaupt möglich, gleichnamige Instanzvariablen in der übergeordneten und untergeordneten Klasse zu definieren?
  • Gibt es Instanzvariablenüberschreibungen und Methodenüberschreibungen? ――Wie jede Sprache die Vererbung selbst handhabt

Ergebnisansage

Java

Java, der Champion der Unternehmenssysteme. Java verfügt über Zugriffsmodifikatoren wie "privat" und "geschützt". "privat" kann nur aus der aktuellen Klasse gesehen werden. Auf protected kann von der aktuellen Klasse und den untergeordneten Klassen aus zugegriffen werden.

In Java gibt es keine Instanzvariablenüberschreibung. Mal sehen, was passiert, wenn wir es mit einer Methode überschreiben.

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariablen sind geschützt "SuperClass"
Private Methode statt Instanzvariable "SuperClass"
Geschützte Methode (Überschreibung) anstelle der Instanzvariablen "SubClass"

Überschreibt wörtlich "überschreiben".

Diesmal war es egal, aber Java ermöglicht Ihnen den Zugriff auf die Instanzvariablen der übergeordneten Klasse mit Methoden auf der Seite der untergeordneten Klasse wie "super.instanceVariable". Es ist ein Trick, den Sie machen können, weil Sie ihn nicht überschreiben.

Code anzeigen (Java)
public class JavaSample {
    public static void main(String[] args) {
        System.out.println("---- SubClass ----");
        SubClass sub = new SubClass();
        sub.superClassMethod();

        System.out.println("---- SubClassProtected ----");
        SubClassProtected subp = new SubClassProtected();
        subp.superClassMethod();

        System.out.println("---- SubClassGetter ----");
        SubClassGetter subg = new SubClassGetter();
        subg.superClassMethod();

        System.out.println("---- SubClassGetterProtected ----");
        SubClassGetterProtected subgp = new SubClassGetterProtected();
        subgp.superClassMethod();
    }
}

class SuperClass {
    //Private Instanzvariablen können nicht von Unterklassen referenziert werden
    private String instanceVariable = "SuperClass";

    public void superClassMethod() {
        System.out.println(instanceVariable);
    }
}

class SubClass extends SuperClass {
    private String instanceVariable = "SubClass";
}

// -------------------------------------------

class SuperClassProtected {
    protected String instanceVariable = "SuperClass";

    public void superClassMethod() {
        System.out.println(instanceVariable);
    }
}

class SubClassProtected extends SuperClassProtected {
    protected String instanceVariable = "SubClass";

    // public void subClassMethod() {
        // System.out.println(instanceVariable);Wenn du schreibst
        // System.out.println(this.instanceVariable);Gleich wie."SubClass"herauskommen.
        //Mit super,"SuperClass"Kann auch angezeigt werden
        // System.out.println(super.instanceVariable);
    // }
}

// -------------------------------------------

class SuperClassGetter {
    private String instanceVariable() {
        return "SuperClass";
    }

    public void superClassMethod() {
        System.out.println(instanceVariable());
    }
}

class SubClassGetter extends SuperClassGetter {
    private String instanceVariable() {
        return "SubClass";
    }
}

// -------------------------------------------

class SuperClassGetterProtected {
    protected String instanceVariable() {
        return "SuperClass";
    }

    public void superClassMethod() {
        System.out.println(instanceVariable());
    }
}

class SubClassGetterProtected extends SuperClassGetterProtected {
    protected String instanceVariable() {
        return "SubClass";
    }
}

C#

Nach Java C #. Es hat eine Grammatik, die Java aus historischen Gründen ziemlich nahe kommt. Das Ergebnis ähnelt auch Java und C ++, aber es gibt einige, die Java nicht hat. Übrigens hat C # Eigenschaften, deshalb habe ich sie als Eigenschaften anstelle von Methoden geschrieben.

C # hat "virtuell" und "überschreiben". virtual ist ein Modifikator, der angibt, dass diese Methode überschrieben werden kann, und override ist ein Modifikator, der angibt, dass die Methode hier überschrieben wird.

Das ist in Ordnung, aber C # hat auch einen seltsamen Modifikator namens "new". Dieses neue unterscheidet sich von dem neuen von "new Human ()" zum Zeitpunkt der Instanziierung. Durch Hinzufügen von new anstelle von override kann die Methode der übergeordneten Klasse im Kontext der übergeordneten Klasse ausgewertet werden, auch wenn sie von einer untergeordneten Klasse aufgerufen wird. Der Grund ist, dass wir die Methoden der übergeordneten Klasse nicht überschreiben, sondern nur ausblenden. Es ist kompliziert.

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariablen sind geschützt "SuperClass"
Eigentum ist privat "SuperClass"
Eigentum geschützt(override) "SubClass"
Eigentum geschützt(new) "SuperClass"
Code anzeigen (C #)
using System;

public class CSharpSample
{
    public static void Main(string[] args)
    {
        Console.WriteLine("---- SubClass ----");
        var sub = new SubClass();
        sub.SuperClassMethod();

        Console.WriteLine("---- SubClassProtected ----");
        var subp = new SubClassProtected();
        subp.SuperClassMethod();

        Console.WriteLine("---- SubClassGetter ----");
        var subg = new SubClassGetter();
        subg.SuperClassMethod();

        Console.WriteLine("---- SubClassGetterProtectedOverride ----");
        var subgpo = new SubClassGetterProtectedOverride();
        subgpo.SuperClassMethod();

        Console.WriteLine("---- SubClassGetterProtectedNew ----");
        var subgpn = new SubClassGetterProtectedNew();
        subgpn.SuperClassMethod();
    }
}

class SuperClass
{
    private string instanceVariable = "SuperClass";

    public void SuperClassMethod()
    {
        Console.WriteLine(instanceVariable);
    }
}

class SubClass : SuperClass
{
    // warning CS0414: The field 'SubClass.instanceVariable' is assigned but its value is never used
    private string instanceVariable = "SubClass";
}

// ----------------------------

class SuperClassProtected
{
    protected string instanceVariable = "SuperClass";

    public void SuperClassMethod()
    {
        Console.WriteLine(instanceVariable);
    }
}

class SubClassProtected : SuperClassProtected
{
    //new ist keine Überschreibung, sondern gibt ausdrücklich an, dass die geerbte Instanzvariable ausgeblendet wird
    new protected string instanceVariable = "SubClass";
}

// ----------------------------

class SuperClassGetter
{
    private string instanceVariable
    { 
        get { 
            return "SuperClass";
        }
    }

    public void SuperClassMethod()
    {
        Console.WriteLine(instanceVariable);
    }
}

class SubClassGetter : SuperClassGetter
{
    private string instanceVariable {
        get {
            return "SubClass";
        }
    }
}

// ----------------------------

class SuperClassGetterProtected
{
    protected virtual string instanceVariable
    { 
        get { 
            return "SuperClass";
        }
    }

    public void SuperClassMethod()
    {
        Console.WriteLine(instanceVariable);
    }
}

class SubClassGetterProtectedOverride : SuperClassGetterProtected
{
    protected override string instanceVariable {
        get {
            return "SubClass";
        }
    }
}

class SubClassGetterProtectedNew : SuperClassGetterProtected
{
    protected new string instanceVariable {
        get {
            return "SubClass";
        }
    }
}

C++

Es scheint, dass C ++ häufig in eingebetteten Sites verwendet wird, aber ich weiß nichts. C ++ Nanimowa Karanai …….

Zusammen mit Java ist es die Originalsprache von C # und sein Verhalten ist C # sehr ähnlich. Wenn Sie eine Methode anstelle einer Instanzvariablen verwenden und diese nicht überschreiben, verhält sie sich wie "neu" in C #.

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariablen sind geschützt "SuperClass"
Private Methode statt Instanzvariable "SuperClass"
Geschützte Methode (Überschreibung) anstelle der Instanzvariablen "SubClass"
Geschützte Methode anstelle der Instanzvariablen (nicht überschreiben) "SuperClass"
Code anzeigen (C ++)
#include <iostream>

class SuperClass {
//Standardmäßig privat (von außerhalb der Klasse nicht zugänglich)
    std::string instanceVariable = "SuperClass";
public:
    void superClassMethod() {
        std::cout << instanceVariable << std::endl;
    }
};

class SubClass : public SuperClass {
    std::string instanceVariable = "SubClass";
};

// -------------------------------

class SuperClassProtected {
protected:
    std::string instanceVariable = "SuperClass";
public:
    void superClassMethod() {
        std::cout << instanceVariable << std::endl;
    }
};

class SubClassProtected : public SuperClassProtected {
protected:
    std::string instanceVariable = "SubClass";
};

// -------------------------------

class SuperClassGetter {
    std::string instanceVariable() {
        return "SuperClass";
    }
public:
    void superClassMethod() {
        std::cout << instanceVariable() << std::endl;
    }
};

class SubClassGetter : public SuperClassGetter {
    std::string instanceVariable() {
        return "SubClass";
    }
};

// -------------------------------

class SuperClassProtectedGetter {
protected:
    std::string instanceVariable() {
        return "SuperClass";
    }
public:
    void superClassMethod() {
        std::cout << instanceVariable() << std::endl;
    }
};

class SubClassProtectedGetter : public SuperClassProtectedGetter {
protected:
    std::string instanceVariable() {
        return "SubClass";
    }
};

// -------------------------------

class SuperClassProtectedGetterOverride {
protected:
    virtual std::string instanceVariable() {
        return "SuperClass";
    }
public:
    void superClassMethod() {
        std::cout << instanceVariable() << std::endl;
    }
};

class SubClassProtectedGetterOverride : public SuperClassProtectedGetterOverride {
protected:
    std::string instanceVariable() override {
        return "SubClass";
    }
};

int main()
{
    std::cout << "---- SubClass ----" << std::endl;
    SubClass sub;
    sub.superClassMethod();

    std::cout << "---- SubClassProtected ----" << std::endl;
    SubClassProtected subp;
    subp.superClassMethod();

    std::cout << "---- SubClassGetter ----" << std::endl;
    SubClassGetter subg;
    subg.superClassMethod();

    std::cout << "---- SubClassProtectedGetter ----" << std::endl;
    SubClassProtectedGetter subpg;
    subpg.superClassMethod();

    std::cout << "---- SubClassProtectedGetterOverride ----" << std::endl;
    SubClassProtectedGetterOverride subpgo;
    subpgo.superClassMethod();

    return 0;
}

Scala

AltJava, das einen funktionalen Stil beinhaltet. Der große Unterschied zu Java und C # besteht darin, dass Sie Instanzvariablen überschreiben können. Neue Funktionen sind da!

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariable geschützt (überschreiben) "SubClass"
Code anzeigen (Scala)
object ScalaSample {
    def main(args: Array[String]): Unit = {
        println("---- SubClass ----")
        val sub = new SubClass
        sub.superClassMethod()
    
        println("---- SubClassProtected ----")
        val subp = new SubClassProtected
        subp.superClassMethod()
    }
}

class SuperClass {
    private val instanceVariable = "SuperClass";

    def superClassMethod(): Unit = {
        println(instanceVariable);
    }
}

class SubClass extends SuperClass {
    private val instanceVariable = "SubClass";
}

// ----------------------------

class SuperClassProtected {
    protected val instanceVariable = "SuperClass";

    def superClassMethod(): Unit = {
        println(instanceVariable);
    }
}

class SubClassProtected extends SuperClassProtected {
    override protected val instanceVariable = "SubClass";
}

Kotlin

Alt Java wurde stark von Scala beeinflusst. Es wird häufig bei der Entwicklung von Android-Apps verwendet. Wie Scala, außer dass die Instanzvariable, die Sie überschreiben möchten, geöffnet sein muss. "Öffnen" ist also wie "virtuell" in C ++ oder C #.

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariable geschützt (überschreiben) "SubClass"
Code anzeigen (Kotlin)
fun main(args: Array<String>) {
    println("---- SubClass ----");
    val sub = SubClass();
    sub.superClassMethod();

    println("---- SubClassOverride ----");
    val subo = SubClassOverride();
    subo.superClassMethod();
}

open class SuperClass {
    private val instanceVariable = "SuperClass";

    fun superClassMethod() {
        println(instanceVariable);
    }
}

class SubClass : SuperClass() {
    private val instanceVariable = "SubClass";
}

// -----------------------------------

open class SuperClassOverride {
    open val instanceVariable = "SuperClass";

    fun superClassMethod() {
        println(instanceVariable);
    }
}

class SubClassOverride : SuperClassOverride() {
    override val instanceVariable = "SubClass";
}

Swift

Android ist nicht die einzige App. Ich möchte nicht, dass du iOS vergisst. Swifts "privat" scheint sich je nach Version unterschiedlich zu verhalten, aber dieses Mal habe ich es mit Swift 5 überprüft. Wie Java ist es nur in der Klasse gültig und wird nicht vererbt.

Swifts let ist eine Variablendeklaration, die eine Neuzuweisung verbietet. In JS ist es "const". Und Swifts var ist eine normale neu zuweisbare Variablendeklaration. Es ist in JS "let". Es ist kompliziert.

In Swift können Sie keine Instanzvariable definieren (in Swift als Eigenschaft bezeichnet), die mit der Vererbungsquelle identisch ist. Sie können es überschreiben, indem Sie stattdessen Computed Property (wie eine Eigenschaft in C #) verwenden.

Ohne einen Zugriffsmodifikator wie "privat" ist der Bereich "intern". "intern" ist wie "öffentlich" in Java (Verschiedenes).

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Die Instanzvariable ist intern Undefinierbar
Das berechnete Eigentum ist privat "SuperClass"
Die berechnete Eigenschaft ist intern(override) "SubClass"
Code anzeigen (Swift)
class SuperClass {
  private let instanceVariable = "SuperClass";

  func SuperClassMethod() {
    print(instanceVariable);
  }
}

class SubClass: SuperClass {
  private let instanceVariable = "SubClass";
}

// --------------------------------

class SuperClassInternal {
  let instanceVariable = "Error";

  func SuperClassMethod() {
    print(instanceVariable);
  }
}

class SubClassInternal: SuperClassInternal {
  // error: cannot override with a stored property 'instanceVariable'
  // let instanceVariable = "SubClass";
}

// --------------------------------

//Machen Sie es zu einer berechneten Eigenschaft und wachsen Sie ein Getter. In diesem Fall wird es als Funktion behandelt, sodass Sie es überschreiben können.
class SuperClassGetter {
  //Wenn es vermietet ist, Fehler: 'let' declarations cannot be computed properties
  private var instanceVariable: String { get { return "SuperClass" } }

  func SuperClassMethod() {
    print(instanceVariable);
  }
}

class SubClassGetter: SuperClassGetter {
  private var instanceVariable: String { get { return "SubClass" } };
}

// --------------------------------

//Machen Sie es zu einer berechneten Eigenschaft und wachsen Sie ein Getter. In diesem Fall wird es als Funktion behandelt, sodass Sie es überschreiben können.
class SuperClassInternalGetter {
  //Wenn es vermietet ist, Fehler: 'let' declarations cannot be computed properties
  var instanceVariable: String { get { return "SuperClass" } }

  func SuperClassMethod() {
    print(instanceVariable);
  }
}

class SubClassInternalGetter: SuperClassInternalGetter {
  override var instanceVariable: String { get { return "SubClass" } };
}

print("---- SubClass ----");
let sub = SubClass();
sub.SuperClassMethod();

print("---- SubClassInternal ----");
let subi = SubClassInternal();
subi.SuperClassMethod();

print("---- SubClassGetter ----");
let subg = SubClassGetter();
subg.SuperClassMethod();

print("---- SubClassInternalGetter ----");
let subig = SubClassInternalGetter();
subig.SuperClassMethod();

Python

Ab hier eine dynamisch getippte Sprache! Python hat seine Popularität solide gemacht und beispielsweise weiterhin den ersten Platz in Qiitas Tag-Posting-Ranking belegt.

Das Merkmal von Python-Klassen ist, dass die Instanz selbst zum ersten Argument der Methode gelangt. Wenn Sie sie deklarieren, schreiben Sie "self" als erstes Argument. Es muss nicht "Selbst" sein, aber jeder schreibt "Selbst".

Danach werden Instanzvariablen wie eine dynamisch typisierte Sprache dynamisch erstellt. Definieren Sie daher die Instanzvariablen im Konstruktor und nicht direkt unter der Klassendeklaration. Dies gilt auch für Ruby und JavaScript.

Python hat keine Zugriffsbeschränkungen für Mitglieder. Es gibt keinen Modifikator "privat". Es ist eine Kultur, die dem Funktionsnamen ** 1 ** voranstellt, um anzuzeigen, dass nicht darauf zugegriffen werden soll.

In Python gibt es jedoch eine Funktion für den Fall, dass ein Namenskonflikt mit einer untergeordneten Klasse besteht. Durch Hinzufügen von ** 2 ** wird der interne Mitgliedsname (Name Mangling) geändert, sodass der ursprüngliche Variablenname nicht mehr zugänglich ist. Mit dieser Funktion können Sie die Ergebnisse zur Laufzeit im Kontext der ursprünglichen übergeordneten Klasse auswerten, auch wenn die untergeordnete Klasse Mitglieder mit demselben Namen hat. pep8-ja - Namenskonvention - Methodenname und Instanzvariable Mal sehen, das Ergebnis.

Bedingungen Ergebnis
Instanzvariable "SubClass"
Methode statt Instanzvariable "SubClass"
Instanzvariable (mit 2 Ansco) "SuperClass"
Methode statt Instanzvariable (mit 2 Ansco) "SuperClass"
Code anzeigen (Python)
class SuperClass:
  def __init__(self):
    self.instance_variable = "SuperClass"

  def super_class_method(self):
    print(self.instance_variable)

class SubClass(SuperClass):
  def __init__(self):
    super().__init__()
    self.instance_variable = "SubClass"

# ------------------------------

class SuperClassNameMangling:
  def __init__(self):
    self.__instance_variable = "SuperClass"

  def super_class_method(self):
    print(self.__instance_variable)

class SubClassNameMangling(SuperClassNameMangling):
  def __init__(self):
    super().__init__()
    self.__instance_variable = "SubClass"

# ------------------------------

class SuperClassGetter:
  def instance_variable(self):
    return "SuperClass"

  def super_class_method(self):
    print(self.instance_variable())

class SubClassGetter(SuperClassGetter):
  def instance_variable(self):
    return "SubClass"

# ------------------------------

class SuperClassNameManglingGetter:
  def __instance_variable(self):
    return "SuperClass"

  def super_class_method(self):
    print(self.__instance_variable())

class SubClassNameManglingGetter(SuperClassNameManglingGetter):
  def __instance_variable(self):
    return "SubClass"

print('---- SubClass ----')
sub = SubClass()
sub.super_class_method()

print('---- SubClassNameMangling ----')
subp = SubClassNameMangling()
subp.super_class_method()

print('---- SubClassGetter ----')
subg = SubClassGetter()
subg.super_class_method()

print('---- SubClassNameManglingGetter ----')
subpg = SubClassNameManglingGetter()
subpg.super_class_method()

Ruby

"Was ist mit einer objektorientierten, dynamisch typisierten Sprache?" Viele Programmierer, die am assoziativen Quiz teilgenommen haben, denken zuerst an diese Sprache.

Ruby hat eine "private", die für Methoden verwendet werden kann, sich aber anders verhält als eine Sprache wie Java. Ich werde nicht im Detail schreiben, weil ich den Empfänger usw. erklären muss, aber vorerst kann ich sagen, dass die Methode, selbst wenn es "privat" ist, im Vererbungsziel zu sehen ist. In Java kann "geschützt" also näher sein. [Ruby] Die Essenz privater Methoden und die Vorteile ihres Verständnisses

In Ruby sind die Namespaces von Variablen und Methoden übrigens getrennt, sodass Sie sie auch dann aufrufen können, wenn Sie die Methoden ohne Klammern schreiben. Die Methode gibt dann das Ergebnis des zuletzt ausgewerteten Ausdrucks zurück, ohne eine Rückgabe zu schreiben. @ @ Variagename ist die Instanzvariable. In Ruby können Sie den Typ (Bereich) einer Variablen anhand des ersten Zeichens des Variablennamens erkennen.

Bedingungen Ergebnis
Instanzvariable "SubClass"
Methode statt Instanzvariable "SubClass"
Private Methode statt Instanzvariable "SubClass"
Code anzeigen (Ruby)
class SuperClass
  def initialize()
    @instance_variable = "SuperClass"
  end

  def super_class_method
    p @instance_variable
  end
end

class SubClass < SuperClass
  def initialize()
    super()
    @instance_variable = "SubClass"
  end
end

# --------------------------------

class SuperClassGetter
  def instance_variable()
    "SuperClass"
  end

  def super_class_method
    p instance_variable
  end
end

class SubClassGetter < SuperClassGetter
  def instance_variable()
    "SubClass"
  end
end

# --------------------------------

class SuperClassGetterPrivate
  def super_class_method
    p instance_variable
  end

  private

  def instance_variable()
    "SuperClass"
  end
end

class SubClassGetterPrivate < SuperClassGetterPrivate
  private
  
  def instance_variable()
    "SubClass"
  end
end

p '---- SubClass ----'
subc = SubClass.new
subc.super_class_method

p '---- SubClassGetter ----'
subg = SubClassGetter.new
subg.super_class_method

p '---- SubClassGetterPrivate ----'
subgp = SubClassGetterPrivate.new
subgp.super_class_method

PHP

PHP hat "private", "geschützte" und "öffentliche" wie Java. Es ist im Grunde nicht in Python, Ruby oder JavaScript! Eifersüchtig! Im Gegensatz zu Java werden "geschützte" Instanzvariablen zum Lesen von Unterklassen verwendet. Dies ist ein Schritt, der mit anderen dynamisch typisierten Sprachen übereinstimmt.

Bedingungen Ergebnis
Die Instanzvariable ist privat "SuperClass"
Instanzvariablen sind geschützt "SubClass"
Private Methode statt Instanzvariable "SuperClass"
Geschützte Methode anstelle der Instanzvariablen "SubClass"
Code anzeigen (PHP)
<?php
function println($message)
{
    echo $message.PHP_EOL;
}

// ----------------------------------------

class SuperClass
{
    private $instanceVariable = "SuperClass";

    public function superClassMethod()
    {
        println($this->instanceVariable);
    }
}

class SubClass extends SuperClass
{
    private $instanceVariable = "SubClass";
}

// ----------------------------------------

class SuperClassProtected
{
    protected $instanceVariable = "SuperClass";

    public function superClassMethod()
    {
        println($this->instanceVariable);
    }
}

class SubClassProtected extends SuperClassProtected
{
    protected $instanceVariable = "SubClass";
}

// ----------------------------------------

class SuperClassGetter
{
    private function instanceVariable()
    {
        return "SuperClass";
    }
    
    public function superClassMethod()
    {
        println($this->instanceVariable());
    }
}

class SubClassGetter extends SuperClassGetter
{
    private function instanceVariable()
    {
        return "SubClass";
    }
}

// ----------------------------------------

class SuperClassGetterProtected
{
    protected function instanceVariable()
    {
        return "SuperClass";
    }
    
    public function superClassMethod()
    {
        println($this->instanceVariable());
    }
}

class SubClassGetterProtected extends SuperClassGetterProtected
{
    protected function instanceVariable()
    {
        return "SubClass";
    }
}

// ----------------------------------------

println("---- SubClass ----");
$sub = new SubClass();
$sub->superClassMethod();

println("---- SubClassProtected ----");
$subp = new SubClassProtected();
$subp->superClassMethod();

println("---- SubClassGetter ----");
$subg = new SubClassGetter();
$subg->superClassMethod();

println("---- SubClassGetterProtected ----");
$subgp = new SubClassGetterProtected();
$subgp->superClassMethod();

JavaScript

Der Front-End-Champion. Eine prototypbasierte objektorientierte Sprache, eine Sprache, die von der Programmiersprache Self inspiriert ist. Da JavaScript in ES6 und höher auch klassenbasiertes Schreiben enthält, kann es von "extensives" geerbt werden.

Bedingungen Ergebnis
Instanzvariable "SubClass"
Instanzvariablen im alten Format "SubClass"
In der Instanzvariablen ist die aufrufende Methode eine Pfeilfunktion "SubClass"
Pfeilfunktion anstelle von Instanzvariable "SubClass"
Code anzeigen (JavaScript)
class SuperClass {
  constructor() {
    this.instanceVariable = "SuperClass"
  }

  superClassMethod() {
    console.log(this.instanceVariable)
  }
}

class SubClass extends SuperClass {
  constructor() {
    super()
    this.instanceVariable = "SubClass"
  }
}

// ------------------------

function LegacySuperClass() {
  this.instanceVariable = "SuperClass";
};
LegacySuperClass.prototype.superClassMethod = function() {
  console.log(this.instanceVariable)
}; 

function LegacySubClass() {
  this.instanceVariable = "SubClass";
};
LegacySubClass.prototype = new LegacySuperClass();

// ------------------------

class SuperClassArrow {
  constructor() {
    this.instanceVariable = "SuperClass"
  }

  superClassMethod = () => {
    console.log(this.instanceVariable)
  }
}

class SubClassArrow extends SuperClassArrow {
  constructor() {
    super()
    this.instanceVariable = "SubClass"
  }
}

// ------------------------

class SuperClassGetterArrow {
  instanceVariable = () => {
    return "SuperClass"
  }

  superClassMethod = () => {
    console.log(this.instanceVariable())
  }
}

class SubClassGetterArrow extends SuperClassGetterArrow {
  instanceVariable = () => {
    return "SubClass"
  }
}

// ------------------------

console.log('---- SubClass ----')
const sub = new SubClass()
sub.superClassMethod()

console.log('---- LegacySubClass ----')
var lsub = new LegacySubClass()
lsub.superClassMethod()

console.log('---- SubClassArrow ----')
const suba = new SubClassArrow()
suba.superClassMethod()

console.log('---- SubClassGetterArrow ----')
const subga = new SubClassGetterArrow()
subga.superClassMethod()

TypeScript

Es ist ein cooles JavaScript, das statisch typisiert werden kann. Es gibt Vereinigungstypen, die den in Haskell mit einem erweiterten Typsystem gefundenen Typen ähnlich sind, und es gibt bedingte Typen, zugeordnete Typen und andere Ausdruckstypen.

In TypeScript führt das Definieren eines Elements mit demselben Namen wie "privat" in einer übergeordneten Klasse und einer untergeordneten Klasse zu einem Kompilierungsfehler. Wenn es "geschützt" ist, gibt es kein Problem. Es ist das genaue Gegenteil von Swift.

Bedingungen Ergebnis
Die Instanzvariable ist privat Undefinierbar
Instanzvariablen sind geschützt "SubClass"
Private Methode statt Instanzvariable Undefinierbar
Die Instanzvariable ist geschützt und die aufrufende Methode ist eine Pfeilfunktion "SubClass"
Geschützte Pfeilfunktion anstelle der Instanzvariablen "SubClass"
Code anzeigen (TypeScript)
class SuperClass {
  private readonly instanceVariable: string

  constructor() {
    this.instanceVariable = "Error"
  }

  public superClassMethod() {
    console.log(this.instanceVariable)
  }
}

class SubClass extends SuperClass {
  //Beim Versuch, mit instanceVariable zu definieren
  // TS2415: Class 'SubClass' incorrectly extends base class 'SuperClass'.
  // private readonly instanceVariable: string

  // constructor() {
  //   super()
  //   this.instanceVariable = "SubClass"
  // }
}

// ------------------------

class SuperClassGetter {
  private instanceVariable() {
    return "Error"
  }

  public superClassMethod() {
    console.log(this.instanceVariable())
  }
}

class SubClassGetter extends SuperClassGetter {
  //Beim Versuch, mit instanceVariable zu definieren
  // TS2415: Class 'SubClassGetter' incorrectly extends base class 'SuperClassGetter'.
  // Types have separate declarations of a private property 'instanceVariable'.
  // private instanceVariable() {
  //   return "SubClass"
  // }
}

// ------------------------

class SuperClassProtected {
  protected readonly instanceVariable: string

  constructor() {
    this.instanceVariable = "SuperClass"
  }

  public superClassMethod() {
    console.log(this.instanceVariable)
  }
}

class SubClassProtected extends SuperClassProtected {
  protected readonly instanceVariable: string
  
  constructor() {
    super()
    this.instanceVariable = "SubClass"
  }
}

// ------------------------

class SuperClassProtectedGetterArrow {
  protected instanceVariable = () => {
    return "SuperClass"
  }

  public superClassMethod = () => {
    console.log(this.instanceVariable())
  }
}

class SubClassProtectedGetterArrow extends SuperClassProtectedGetterArrow {
  protected instanceVariable = () => {
    return "SubClass"
  }
}

// ------------------------

//Pfeilfunktionsversion
class SuperClassProtectedArrow {
  protected readonly instanceVariable: string

  constructor() {
    this.instanceVariable = "SuperClass"
  }

  public superClassMethod = () => {
    console.log(this.instanceVariable)
  }
}

class SubClassProtectedArrow extends SuperClassProtectedArrow {
  protected readonly instanceVariable: string
  
  constructor() {
    super()
    this.instanceVariable = "SubClass"
  }
}

console.log('---- SubClass ----')
const sub = new SubClass()
sub.superClassMethod()

console.log('---- SubClassGetter ----')
const subg = new SubClassGetter()
subg.superClassMethod()

console.log('---- SubClassProtected ----')
const subp = new SubClassProtected()
subp.superClassMethod()

console.log('---- SubClassProtectedArrow ----')
const subpa = new SubClassProtectedArrow()
subpa.superClassMethod()

console.log('---- SubClassProtectedGetterArrow ----')
const subpga = new SubClassProtectedGetterArrow()
subpga.superClassMethod()

Dart

Es ist eine beeindruckende Sprache, die plötzlich präsent ist, seit Flutter populär wurde. Dart schreibt nicht "privat" oder "öffentlich". Sie können es privat machen, indem Sie dem Mitgliedsnamen einen Unterstrich hinzufügen. Es unterscheidet sich jedoch von "privat" wie Java, da es nur von außerhalb der Bibliothek unsichtbar wird.

Bedingungen Ergebnis
Instanzvariable (mit ansco) "SubClass"
Instanzvariable "SubClass"
Methode statt Instanzvariable "SubClass"
Code anzeigen (Dart)
void main() {
  print("---- SubClassPrivate ----");
  final subp = new SubClassPrivate();
  subp.superClassMethod();

  print("---- SubClass ----");
  final sub = new SubClass();
  sub.superClassMethod();

  print("---- SubClassGetter ----");
  final subg = new SubClassGetter();
  subg.superClassMethod();
}

class SuperClassPrivate {
  //Wenn Sie einen Unterstrich geben, ist dieser privat,
  //Da privat für dieselbe Bibliothek sichtbar ist, sieht es in der Unterklasse hier normal aus
  final String _instanceVariable = "SuperClass";

  void superClassMethod() => print(_instanceVariable);
}

class SubClassPrivate extends SuperClassPrivate {
  final String _instanceVariable = "SubClass";
}

// ------------------------------------

class SuperClass {
  final String instanceVariable = "SuperClass";

  void superClassMethod() => print(instanceVariable);
}

class SubClass extends SuperClass {
  final String instanceVariable = "SubClass";
}

// ------------------------------------

class SuperClassGetter {
  String instanceVariable() => "SuperClass";

  void superClassMethod() => print(instanceVariable());
}

class SubClassGetter extends SuperClassGetter {
  String instanceVariable() => "SubClass";
}

Zusammenfassung

Es hat überraschend viel Spaß gemacht, denn es gab Dinge, die ich selbst in einer Sprache, die ich bis zu einem gewissen Grad gewohnt war, nicht kannte. Einige der Beispiele, die ich dieses Mal zum ersten Mal geschrieben habe, so schreibe ich es! Oder etwas stimmt nicht! Bitte kommentieren Sie, wenn Sie welche haben.

Insgesamt hatte ich den Eindruck, dass in einer dynamisch typisierten Sprache selbst beim Aufrufen einer Oberklassenmethode diese zunächst im Kontext einer Unterklasse ausgewertet wird. Andererseits lautete die statisch typisierte Sprache wie folgt: "Da es sich um eine Methode einer Oberklasse handelt, werden die Grundlagen von der Oberklasse bewertet. Wenn Sie sie jedoch überschreiben, ist dies nicht der Fall."

Die folgenden fünf waren persönlich beeindruckend.

--C # hat einen nicht überschreibenden Modifikator namens "new"

  • Scala und Kotlin sind statisch typisierte Sprachen, können jedoch Instanzvariablen überschreiben
  • Python-Unterstrich Die beiden Mitgliedsnamen waren mehr als nur Namen, sie wirkten sich auch aus --PHP hat ein "privates" wie Java, obwohl es eine dynamisch typisierte Sprache ist --TypeScript verhindert, dass doppelte "private" Mitglieder mit demselben Namen beim Kompilieren einen Fehler verursachen und unerwartetes Verhalten verursachen.

Änderungsprotokoll

  • Ein Fehler in der Erklärung der Python-Namenskonvention wurde behoben. Vielen Dank, dass Sie @shiracamus.
  • Es wurde darauf hingewiesen, dass das Wort "privat" in Python nicht verwendet wird, also habe ich es behoben. Danke @Luice.

Recommended Posts