2009-03-05 4 views
1

Ok, lassen wir die Debatte, ob Freundschaft Einkapselung bricht, und tatsächlich versuchen, elegant mit einem kohärenten Design zu kommen. Es ist eine zweifache Funktion:Implementieren von Freunden (verfügbar in C++) Funktionalität in Java

1) Allgemeine Frage, wie zu implementieren:

public class A 
    { 
     friend class B; 
    } 

2) Warum muss ich diese Funktionalität? Einige meiner Klassen implementieren eine serialisierbare Schnittstelle. Ich möchte jedoch Serializable-Methoden in der Klasse Abgeleitete schützen, so dass ich sie nicht einem Client aussetze (ebenso wie in der Dokumentation - javadoc). Interne Klassen sollten jedoch in der Lage sein, auf sie zuzugreifen. Was ist der allgemeine Weg, um dieses Problem in Java zu lösen?

Hinweis: Ich verwende Freundschaft wie im aktuellen C++ - Standard definiert.

Dank

+0

Does Java unterstützen eine "interne" Modifikator wie C# tut? In C# können Sie intern verwenden, um Dinge nur innerhalb derselben Baugruppe sichtbar zu machen. – OregonGhost

+0

Wirklich nicht genug Informationen. Sollten serialisierbare Methoden sowieso nicht privat sein. –

+0

Ja, Sie brauchen keinen Zugriff auf die Serialisierungsmethoden, um Objekte zu serialisieren. Das scheint argumentativ und auch keine Frage ... – wds

Antwort

6

Die allgemeine Lösung ist die Methoden Paket-private zu machen (das ist die Ebene Standard-Schutz in Java). Auf diese Weise kann jeder Code in demselben Paket auf sie zugreifen, aber kein externer Code.

Java erlaubt keine willkürliche Freigabe von Methoden mit bestimmten externen Klassen.

EDIT: Geschützte Mitglieder sind eigentlich weniger private als Paket-private. Wenn Sie über geschützte Mitglieder verfügen, können Sie auf sie von abgeleiteten Klassen außerhalb Ihres Pakets und von jeder Klasse innerhalb des Pakets zugreifen. Das könnte also eine Lösung für Ihr Problem sein - leiten Sie die Klasse in einer anderen Klasse in dem Paket ab, in das Sie exportieren möchten.

Im Allgemeinen betrachtet Java das Paket als Hauptmodul der Kapselung. Die public/protected-Schnittstelle ist für Klassen außerhalb des Pakets vorgesehen, und die Standardschutzebene ermöglicht den Zugriff innerhalb des Pakets.

+0

Nun, ich muss auf sie auch von anderen internen Paketen zugreifen :( –

+0

Paket-private (Standardzugriff) sollte ziemlich selten sein für alles außer Top-Level-Typen. –

+0

@Tom: Ich stimme zu. Ich habe nur darauf hingewiesen, dass es ist der einzige offiziell unterstützte Weg, Interna überhaupt zu teilen. – Avi

2

Es scheint, als ob Sie eine Fassade wollen.

Sie scheinen eine Klasse zu haben, die öffentlichen Zugriff auf verschiedene andere Klassen (selbst in verschiedenen Paketen) gewähren muss, die an der Implementierung beteiligt sind. Aber Sie möchten nicht, dass Kunden Zugriff haben.

Daher machen Sie die Implementierung so kompliziert wie Sie möchten. Lassen Sie eine Fassadenklasse mit der gewünschten Schnittstelle an die Implementierung delegieren.

0

Eine Sache, die ich bemerkte ... es klingt wie Sie nicht die Methoden möchten, die Sie überschreiben müssen, weil Sie Serializable implementieren, um öffentlich zu werden. Eine Sache ist jedoch, Serializable ist eine Marker-Schnittstelle (es bietet keine Methoden, um überschrieben werden) und die readObject und writeObject-Methoden sollen privat sein.

Fehle ich etwas?

0

Es gibt zwei Lösungen für Ihre Frage, bei denen nicht alle Klassen im selben Paket enthalten sein müssen.

Die erste ist, das Friend Accessor/Friend Package Muster zu verwenden, das in (Practical API Design, Tulach 2008) beschrieben wird.

Die zweite ist, OSGi zu verwenden. Es gibt einen Artikel here, der erklärt, wie OSGi dies erreicht.

Verwandte Fragen: 1, 2, 3 und 4.

2

Dieser Link gibt einen Weg, Freund Zugriff in Java zu emulieren: http://macchiato.com/columns/Durable7.html

Der Code aus dem Link kopiert (falls die Website nicht erreichbar ist):

public class A { 
private int privateInt = 31415; 

public class SomePrivateMethods { 
    public int getSomethingPrivate() { return privateInt; } 
    private SomePrivateMethods() {} // no public constructor 
} 
public void giveKeyTo(B other) { 
    other.receiveKey(new SomePrivateMethods()); 
} 
} 

public class B { 
private A.SomePrivateMethods key; 

public void receiveKey(A.SomePrivateMethods key) { 
    this.key = key; 
} 

public void usageExample() { 
    A anA = new A(); 

    //int foo = anA.privateInt; // doesn't work, not accessible 

    anA.giveKeyTo(this); 
    int fii = key.getSomethingPrivate(); 
    System.out.println(fii); 
} 
} 
Verwandte Themen