Ist es akzeptabel, Objekte des gleichen Typs in sich selbst zu deklarieren?

8

Ist es akzeptabel, neue Objekte innerhalb desselben Objekts zu deklarieren (und zurückzugeben), wie im folgenden Beispiel?

Oder ist es besser, es in eine handlerKlasse zu verschieben?

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    //Gets a list of persons
    public List<Person> GetPersons()
    {
        List<Person> _listPersons = new List<Person>();

        Person _person = new Person();
        _person.Name = "FooFii"; 
        _person.Age = 50;
        _listPersons.Add(_person); 

        return _listPersons; 
    }
}
AsusT9
quelle
6
Je nach Sprache würde ich empfehlen GetPersons, statisch zu sein oder kein Mitglied von Person zu sein. Derzeit müssen Sie PersonanrufenGetPersons
Caleth
Sicher, die Java- ObjectKlasse (die Wurzel der Klassenhierarchie) schreibt explizit eine clone()Methode vor, die eine Kopie des Objekts bereitstellen soll.
TMN

Antworten:

9

Im Allgemeinen ist es ja in Ordnung . Im Allgemeinen wird im Konstruktor einer Klasse das gesamte Setup ausgeführt, das für die Funktion dieser Klasse erforderlich ist. Oft wird ein Teil dieses Setups in andere Bereiche des Codes abstrahiert. Zum Beispiel verschiebt das Factory-Muster einen Großteil des anfänglichen Setups in eine andere Klasse, sodass das Setup klar von der Logik getrennt ist.

In Ihrem speziellen Beispiel ist das nicht in Ordnung . Vielleicht , weil Ihr Beispiel aufgebaut ist , aber Sie sind conflating Daten und Logik. Sie erklären, wie eine Person aussieht, und geben mir Methoden, wie ich bestimmte Personen erreichen kann. Es lohnt sich, das Prinzip der Einzelverantwortung zu untersuchen . In Ihrem Beispiel hätte ich eine einfache Klasse, die den Datentyp von Person definiert, ein Repository, das Personen abruft, und eine Klasse, die Personen aus dem Repository herausholt und dann etwas mit den Daten macht (dh sie per E-Mail versendet).

Tom Squires
quelle
5

Ja, unter den richtigen Bedingungen.

Ein häufiges Beispiel ist die Filterzusammensetzung. Hier erstellen Sie einen neuen Filter, indem Sie eine Methode für einen älteren Filter aufrufen.

Erfundenes Beispiel:

class Filter {
    public function where(string field_name, object value) {
        filters = (clone)this->filters;
        filters.setitem(field_name, value);
        return Filter(filters);
    }
}

Dies ermöglicht eine Verwendung wie

query = Filter()
    .where("username", "nobody")
    .where("password", "should be salted and hashed")
;
user = User.get(filter);

So funktioniert die Verkettung von jQuery-Selektoren und die Funktionsweise von Django-Abfragesätzen.

Sjoerd Job Postmus
quelle
3

Anstatt es so zu machen, würde ich versuchen, so etwas wie eine gekapselte Version des Factory-Musters zu implementieren. Haben Sie ein separates Objekt, das stattdessen die Liste erstellt. Siehe Factory (objektorientierte Programmierung) .

Sie führen im Wesentlichen bereits das Factory-Muster aus, wenn Sie eine Liste von zurückgeben Person. Stattdessen möchten Sie möglicherweise zwei separate Klassen haben. Wenn Sie die Factory vom Produkt trennen , wird Ihre Implementierung von Personnicht an Ihre Klasse gebunden, die die Liste erstellt (dh PersonFactory).

Wenn Sie den obigen Link sehen, sehen Sie, dass ein ähnliches Beispiel wie Sie tatsächlich im Abschnitt mit den beschreibenden Namen veröffentlicht wird. Aus dem oben genannten Grund würde ich es jedoch nicht so machen. Siehe den Abschnitt über die Kapselung (auch im Link).

Schnüffeln
quelle
1

Ich kann Ihnen ein Beispiel geben, und es ist nicht falsch, Objekte vom gleichen Typ innerhalb desselben Typs zurückzugeben.

Bedenken Sie.

class Employee {}

class Manager : Employee 
{
    List<Employee> Employees { get; set;}
    Manager ReportsTo { get; set; }
}

Es gibt eine dünne Linie zwischen Trennung oder Vermischung von Bedenken. Wenn Sie sich auf der anderen Seite dieser Zeile befinden, können Sie einen Manager / Handler / ... verwenden, um ein Objekt zu sortieren.

class Organization 
{
    Employee FindEmployeeByName (string name) {}
    Employee FindManagerOf (Employee emp) {}
    List<Employees> TeamOf (Employee manager)
    ...
}
Kaan
quelle