Ich habe mich gefragt, ob es einen gültigen Anwendungsfall gibt, um die spezifischen internen Eigenschaften und Funktionen einer Klasse auf ähnliche Weise wie eine Schnittstelle die öffentlichen Eigenschaften und Funktionen einer Klasse definieren zu können.
Stellen Sie sich die Aufgabe vor, eine Klasse aufzubauen, die einen Menschen beschreibt.
Offensichtlich ist jeder Mensch eine humanoide Kreatur, aber nicht jede humanoide Kreatur ist ein Mensch. Sie hätten also wahrscheinlich eine Schnittstelle IHumanoid mit Funktionen wie diesen (da es nicht sinnvoll ist, den Körperplan in der Klasse fest zu codieren):
public interface IHumanoid {
function get head():IHead;
function get torso():ITorso;
function get leftArm():IArm;
function get rightArm():IArm;
function get leftLeg():ILeg;
function get rightLeg():ILeg;
}
Weiter und offensichtlich ist jeder Mensch ein Säugetier, aber nicht jedes Säugetier ist ein Mensch, daher gibt es wahrscheinlich eine andere IMammal-Schnittstelle mit zwei Definitionen für Männer und Frauen, die irgendwo herumschweben:
public interface IMammal {
function procreate(partner:IMammal):void;
}
public interface IMaleMammal extends IMammal {
function inseminate(female:IFemaleMammal):void;
}
public interface IFemaleMammal extends IMammal {
function conceive(partner:IMaleMammal):Boolean;
function giveBirth():IMammal;
function nurse(offspring:IMammal):void;
}
So sieht unsere Klasse jetzt wahrscheinlich ungefähr so aus:
public class Human implements IHumanoid, IMammal {
private var _head:IHead;
private var _torso:ITorso;
private var _leftArm:IArm;
private var _rightArm:IArm;
private var _leftLeg:ILeg;
private var _rightLeg:ILeg;
public function Human() {
// ctor...
}
public function get head():IHead {
return _head;
}
public function get torso():ITorso {
return _torso;
}
public function get leftArm():IArm {
return _leftArm;
}
public function get rightArm():IArm {
return _rightArm;
}
public function get leftLeg():ILeg {
return _leftLeg;
}
public function get rightLeg():ILeg {
return _rightLeg;
}
public function procreate(partner:IMammal):void {
// "abstract" function
}
}
public class MaleHuman extends Human implements IMaleMammal {
override public function procreate(partner:IMammal):void {
if (partner is IFemaleMammal) {
inseminate(partner);
}
}
public function inseminate(female:IFemaleMammal):void {
female.conceive(this);
}
}
public class FemaleHuman extends Human implements IFemaleMammal {
override public function procreate(partner:IMammal):void {
if (partner is IMaleMammal) {
conceive(partner);
}
}
public function conceive(partner:IMaleMammal):Boolean {
// ...
}
public function giveBirth():IMammal {
// ...
}
public function nurse(offspring:IMammal):void {
// ...
}
}
Von hier aus können wir unsere Klassen weiter implementieren und alles funktioniert gut und gut, bis wir die Aufgabe bekommen, die vorhandenen Schnittstellen zu verwenden, um einige andere Klassen zu implementieren. Vielleicht ein Gorilla, ein Orca und ein Schnabeltier.
Wenn wir das massive Problem ignorieren, das das Schnabeltier für unsere aktuelle Schnittstellenstruktur darstellt (* Husten * Eiablagesäugetier * Husten *), haben wir das "Problem", dass uns nichts daran hindert, dem Gorilla 2 Gehirn, der Orca 8 Lunge und der Schnabeltierhälfte zu geben ein Dutzend Lebern. Und obwohl wir diszipliniert genug sind, um der Struktur zu folgen, die Säugetiere normalerweise haben, können wir dies nicht garantieren, wenn wir die API für andere Entwickler öffnen, die möglicherweise einige ernsthaft vermasselte Dinge codieren, die für die Außenwelt immer noch in Ordnung aussehen.
Daher habe ich mich gefragt, ob es einen gültigen Anwendungsfall gibt, um so etwas wie eine "private Schnittstelle" zu erstellen, die nicht öffentliche Funktionen und Eigenschaften definiert. Vielleicht etwas in diese Richtung:
public structure SMammal {
function get brain():IBrain;
function get liver():ILiver;
function get leftLung():ILung;
function get rightLung():ILung;
function get leftKidney():IKidney;
function get rightKidney():IKidney;
}
public class Human implements IHumanoid, IMammal follows SMammal {
private function get brain():IBrain {
// ...
}
private function get liver():ILiver {
// ...
}
// etc. etc.
}
Gibt es eine solche Funktion in einer Programmiersprache? Können abstrakte Klassen verwendet werden, um dies zu lösen? Oder sollten wir uns überhaupt nicht darum kümmern, solange die öffentliche Schnittstelle irgendwie wie erwartet funktioniert?