Frage

Wie beurteilen Sie diese Designentscheidung?Welche Vorteile hat es und welche Nachteile?

Links:

War es hilfreich?

Lösung

In einem Kommentar haben Sie sich gefragt, ob die Einbettungsidee ausreichte, um "die Vererbung vollständig zu ersetzen". Ich würde sagen, die Antwort auf diese Frage lautet "Ja". Vor ein paar Jahren habe ich sehr kurz mit einem Tcl oo -System genannt Snit, die Komposition und Delegation unter Ausschluss der Vererbung verwendete. Snit unterscheidet sich immer noch stark von GOs Ansatz, aber in dieser Hinsicht haben sie einen gemeinsamen philosophischen Boden. Es ist ein Mechanismus, um Funktionen der Funktionalität und Verantwortung zusammenzuschließen, keine Hierarchie für die Klassen.

Wie andere gesagt haben, geht es wirklich darum, welche Art von Programmierpraktiken die Sprachdesigner unterstützen möchten. Alle diese Entscheidungen haben ihre eigenen Vor- und Nachteile; Ich denke nicht, dass "Best Practices" ein Satz ist, der hier notwendigerweise gilt. Wir werden wahrscheinlich sehen, dass jemand irgendwann eine Vererbungsschicht für Go entwickelt.

(Für alle mit TCL vertrauten Leser fühlte ich mich ein wenig enger mit dem "Gefühl" der Sprache als in der Sprache zusammen. [incr Tcl] war. Bei TCL dreht sich alles um die Delegation, zumindest auf meine Denkweise.)

Andere Tipps

Das Bande von 4"Das entscheidende Prinzip ist" die Zusammensetzung der Vererbung bevorzugen "; gehen macht Du folgst ihm ;-).

Die einzigen wirklichen Verwendungszwecke der Vererbung sind:

  • Polymorphismus

    • Das „Static Duck Typing“-System der Go-Schnittstelle löst dieses Problem
  • Ausleihen einer Implementierung aus einer anderen Klasse

    • Dafür ist die Einbettung da

Der Ansatz von Go bildet nicht genau 1:1 ab. Betrachten Sie dieses klassische Beispiel für Vererbung und Polymorphismus in Java (basierend auf):

//roughly in Java (omitting lots of irrelevant details)
//WARNING: don't use at all, not even as a test

abstract class BankAccount
{
    int balance; //in cents
    void Deposit(int money)
    {
        balance += money;
    }

    void withdraw(int money)
    {
        if(money > maxAllowedWithdrawl())
            throw new NotEnoughMoneyException();
        balance -= money;
    }

    abstract int maxAllowedWithdrawl();
}

class Account extends BankAccount
{
    int maxAllowedWithdrawl()
    {
        return balance;
    }
}

class OverdraftAccount extends BankAccount
{
    int overdraft; //amount of negative money allowed

    int maxAllowedWithdrawl()
    {
        return balance + overdraft;
    }
}

Hier werden Vererbung und Polymorphismus kombiniert, und Sie können dies nicht in Go übersetzen, ohne die zugrunde liegende Struktur zu ändern.

Ich habe mich noch nicht intensiv mit Go beschäftigt, aber ich vermute, dass es ungefähr so ​​aussehen würde:

//roughly Go? .... no?
//for illustrative purposes only; not likely to compile
//
//WARNING: This is totally wrong; it's programming Java in Go

type Account interface {
    AddToBalance(int)
    MaxWithdraw() int
}

func Deposit(account Account, amount int) {
    account.AddToBalance(amount)
}

func Withdraw(account Account, amount int) error {
    if account.MaxWithdraw() < amount {
        return errors.New("Overdraft!")
    }
    account.AddToBalance(-amount)
    return nil
}

type BankAccount {
    balance int
}

func (account *BankAccount) AddToBalance(amount int) {
    account.balance += amount;
}

type RegularAccount {
    *BankAccount
}

func (account *RegularAccount) MaxWithdraw() int {
    return account.balance //assuming it's allowed
}

type OverdraftAccount {
    *BankAccount
    overdraft int
}

func (account *OverdraftAccount) MaxWithdraw() int {
    return account.balance + account.overdraft
}

Dem Hinweis zufolge ist dies eine völlig falsche Art des Codierens, da man Java in Go ausführt.Wenn man so etwas in Go schreiben würde, wäre es wahrscheinlich ganz anders organisiert.

Die Einbettung bietet eine automatische Delegation. Dies an sich nicht ausreicht, um die Vererbung zu ersetzen, da die Einbettung keine Form des Polymorphismus bietet. GO -Schnittstellen liefern Polymorphismus, sie unterscheiden sich etwas von den Schnittstellen, mit denen Sie möglicherweise verwendet werden (manche Menschen vergleichen sie mit der Enten -Typisierung oder der Strukturierung).

In anderen Sprachen müssen Erbschafthierarchien sorgfältig gestaltet werden, da Änderungen weitgehend und daher schwer zu erledigen sind. GO vermeidet diese Fallstricke und bietet eine starke Alternative.

Hier ist ein Artikel, der mit etwas mehr in OOP eintaucht: http://nathany.com/good

Ich lerne gerade etwas über Go, aber da Sie um eine Meinung fragen, werde ich eine basierend auf dem anbieten, was ich bisher weiß. Die Einbettung scheint typisch für viele andere Dinge in Go zu sein, was explizite Sprachunterstützung für Best Practices ist, die bereits in vorhandenen Sprachen durchgeführt werden. Wie Alex Martelli beispielsweise bemerkte, sagt die 4 -Band -Bande "Ziehen Sie die Komposition der Erbschaft vor". Entfernt nicht nur die Vererbung, sondern erleichtert die Komposition auch in C ++/Java/C#.

Ich war verwirrt von Kommentaren wie "Go bietet nichts Neues, das ich in Language X noch nicht tun kann" und "Warum brauchen wir eine andere Sprache?" Es scheint mir, dass Go in gewisser Hinsicht nichts Neues bietet, das vorher nicht mit etwas Arbeit getan werden konnte, aber in einem anderen Sinne ist das Neue, dass Go die Verwendung der besten Techniken erleichtert und fördert Bereits in der Praxis mit anderen Sprachen.

Die Leute haben Links zu Informationen über ein Einbettung in Go angefordert.

Hier ist ein "effektives GO" -Dokument, in dem ein Einbettung diskutiert wird und wo konkrete Beispiele bereitgestellt werden.

http://golang.org/doc/effective_go.html#embedding

Das Beispiel ist sinnvoller, wenn Sie bereits ein gutes Verständnis für GO -Schnittstellen und -Typen haben, aber Sie können sie vortragen, indem Sie an eine Schnittstelle als Name für eine Reihe von Methoden denken und wenn Sie eine Struktur als ähnlich einer C -Struktur betrachten.

Weitere Informationen zu Strukturen finden Sie in der GO -Sprachspezifikation, in der namenlose Mitglieder von Strukturen als eingebettete Typen ausdrücklich erwähnt werden:

http://golang.org/ref/spec#struct_types

Bisher habe ich es nur als bequeme Möglichkeit verwendet, eine Struktur in eine andere zu setzen, ohne einen Feldnamen für die interne Struktur verwenden zu müssen, wenn ein Feldname dem Quellcode keinen Wert hinzufügt. In der folgenden Programmierübung bündle ich einen Vorschlagstyp innerhalb eines Typs mit einem Vorschlag und einem Antwortkanal.

https://github.com/ecashin/go-getting/blob/master/bpaxos.go#l30

Ich mag das.

Die Sprache, die Sie verwenden, wirkt sich auf Ihre Gedankenmuster aus. (Bitten Sie einfach einen C -Programmierer, "Wortanzahl" zu implementieren. Sie werden wahrscheinlich eine verknüpfte Liste verwenden und dann zur Leistung zu einem binären Baum wechseln. Aber jeder Java/Ruby/Python -Programmierer wird ein Wörterbuch/Hash verwenden. Die Sprache hat ihre beeinflusst Verhirn so sehr, dass sie sich nicht daran vorstellen können, eine andere Datenstruktur zu verwenden.)

Mit der Vererbung müssen Sie aufbauen - beginnen Sie mit dem abstrakten Ding und subklassen Sie es dann in die Einzelheiten. Ihr tatsächlicher nützlicher Code wird in einer tiefen Klasse der Klasse n vergraben. Dies macht es schwierig, einen "Teil" eines Objekts zu verwenden, da Sie Code nicht wiederverwenden können, ohne über übergeordnete Klassen zu ziehen.

In Go können Sie Ihre Klassen auf diese Weise "modellieren" (mit Schnittstellen). Aber Sie können auf diese Weise nicht codieren.

Stattdessen können Sie Einbettung verwenden. Ihr Code kann in kleine, isolierte Module mit jeweils eigenen Daten unterteilt werden. Dies macht die Wiederverwendung trivial. Diese Modularität hat wenig mit Ihren "großen" Objekten zu tun. (dh in Go können Sie eine "quack ()" -Methode schreiben, die nicht einmal über Ihre Entenklasse weiß. In einer typischen OOP -Sprache können Sie jedoch nicht deklarieren. Alle anderen Methoden der Ente. ")

In Go zwingt dies den Programmierer ständig, über Modularität nachzudenken. Dies führt zu Programmen mit geringer Kopplung. Eine niedrige Kopplung erleichtert die Wartung erheblich. ("Oh, schau, duck.quack () ist wirklich lang und komplex, aber zumindest weiß ich, dass es nicht vom Rest der Ente abhängt.")

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top