W
Boh - was für ein langer Thread.
Grundsätzlich stehe ich hinter der Meinung die Nexus vertritt.
Bei mir haben auch 2D/3D-Vektoren, Brüche oder Komplexe Zahlen keine Set-Methoden und selbstverständlich sind deren Member privat. Ich habe auch nie so eine Set-Methode vermisst. Das heißt nicht, dass ich nicht auch kleine Strukturen mit public-Membern benutze, wo es Sinn macht.
Aber ein SetNenner bei einem Bruch macht IMHO soviel Sinn, wie ein SetDezimalZiffer-Methode bei einem int oder ein SetSinusWert bei einem Winkel. Zu diesem Thema hatte ich schon mal eine längere Diskussion.
Noch mal ein kleines Beispiel, um das was Nexus schon gesagt hat, zu unterstreichen. Mal angenommen man soll eine Klasse Statistik erstellen, die Mittelwert und Standardabweichung berechnet. Dann habe ich hier im Forum schon Ansätze gesehen, die in etwa so aufgebaut waren:
class Statistik
{
public:
std::vector< double >& getDaten();
void berechne();
double getMittelwert();
double getStandardabweichung();
private:
double mittelwert;
double standardabweichung;
std::vector< double > daten;
};
Da hat sich einer überlegt, dass man zur Bestimmung von Mittelwert und Standardabweichung alle Werte und zwei Variablen für das Ergebnis benötigt. getDaten() liefert den vector , den kann man dann schön mit Werten füllen, anschließend ruft man berechne() auf und hol dann mit den get-Methoden die Ergebnisse ab. Da alles in einer Klasse 'gekapselt' ist, soll es dann objektorientiert sein.
Wenn man sich in die Position des Anwenders dieser Klasse versetzt, ist das aber so gar nicht notwendig. Der Anwender will vielleicht nur eine Ausgabe in ein Protokoll über Mittelwert und Standardabweichung. Was er wirklich nur dazu tun muss ist, dem Objekt die einzelnen Werte mitzuteilen. Also vielleicht so:
class Statistik
{
public:
Statistik();
void add( double value );
friend std::ostream& operator<<( std::ostream& out, const Statistik& s );
private:
std::size_t n_;
double mean_, m2_; // siehe http://www.c-plusplus.net/forum/p2270075#2270075
};
Der Anwender hat hier keine Chance das berechne() zu vergessen. Wenn er ein Objekt dieser Klasse auf den std::ostream ausgibt, bekommt er immer das aktuelle Ergebnis. Und intern wird der vector gar nicht benötigt, wie man auch bei Wiki nachlesen kann.
Der Unterschied ist, dass man mit der ersten Lösung das Innere der Klasse nach außen kehrt und damit auch die Art der Implementierung - zumindest teilweise - fixiert. Beim zweiten Ansatz ist das nicht der Fall. Das Interface ist kondensiert auf das, was der Anwender in diesem Fall benötigt. In einem anderen Projekt kann das natürlich anders aussehen.
Gruß
Werner