2009-08-27 6 views
0

Ich möchte wissen, ob man über eine Basisklasse Eigenschaft von einer abgeleiteten Klasse verstecken:C# verstecken von dervied Klassen einige Eigenschaften der Basisklasse

Beispiel:

class BaseDocument 
    { 
     public string DocPath{get; set;} 
     public string DocContent{get; set;} 
    } 

    class DerviedDocument: BaseDocument 
    { 
    //this class should not get the DocContent property 
     public Test() 
     { 
      DerivedDocument d = new DerivedDocument(); 
      d.//intellisense should only show me DocPath 
      //I do not want this class to see the DocContent property 
     } 
    } 

Ich kann die docContent Eigenschaft machen privat, weil ich die BaseDocument-Klasse an anderer Stelle instanziieren und die Eigenschaft dort verwenden möchte. Das wird die Idee einer Eigenschaft sowieso töten.

Eine Möglichkeit, dies zu beheben, wäre die Verwendung einer Schnittstelle, sagen IDoc, die DocPath-Eigenschaft verfügbar macht und sowohl die BaseDocument und DerivedDocument implementieren die Schnittstelle. Dies wird jedoch ihre Eltern-Kind-Beziehung brechen.

kann ich mit dem neuen spielen und Schlüsselwort außer Kraft setzen, aber das ist nicht der richtige Weg wäre es, weil das Kind noch ‚sieht‘ die Eigenschaft

Ich versuchte, das ‚versiegelt‘ Schlüsselwort auf der docContent verwenden, aber das bedeutet nicht scheinen auch das Problem zu lösen.

Ich verstehe, dass es "Vererbung" Vererbung, aber ich denke, dieses Szenario sollte häufig kommen, wo ein Kind alles andere von der übergeordneten, aber ein oder zwei Eigenschaften erhalten muss.

Wie können solche Szenarien elegant gehandhabt werden?

+0

Warum möchten Sie das tun? – ChaosPandion

+0

Ich habe ein existierendes Szenario, das der Frage ähnlich ist. Und außerdem, ich bin nur neugierig zu wissen! – desigeek

+0

Wie andere bereits erwähnt haben, sollten Sie nicht von der Basis abgeleitet werden, wenn dies der Fall ist. Abgeleitete Klassen sollen die Basisklassenschnittstelle vollständig unterstützen. Wenn mein Programm mit CBase arbeitet, sollte sein Verhalten unverändert bleiben, auch wenn ich es mit irgendeinem CDerived für CBase - http://www.objectoror.com/resources/articles/lsp.pdf – Gishu

Antwort

3

Ich bin nicht sicher, Vererbung wäre der Weg, hier zu gehen. Ja, Sie können es umgehen, indem Sie die EditorBrowsableAttribute verwenden, aber ich denke, das Design sollte überdacht werden. Eine mögliche Lösung:

public interface IDoc 
{ 
    DocPath{get;set;} 
} 

class BaseDocument : IDoc 
{ 
    public DocPath{get; set;} 
    public DocContent{get; set;} 
} 

class DerviedDocument 
{ 
    public DerivedDocument(IDoc doc) 
    { 
     this.Doc = doc; 
    } 

    public IDoc Doc{get;set;} 

    public Test() 
    { 
     DerivedDocument d = new DerivedDocument(new BaseDocument()); 
     d.//here you will only see d.IDoc which only exposes DocPath 

    } 
} 

Verwenden Sie im Grunde Komposition statt Vererbung und Programm auf eine Schnittstelle, nicht auf eine Implementierung.

+0

Schön, das ist eine gute Lösung –

+1

Sie sollten auch den Namen DerivedDocument ändern, um Missverständnisse zu vermeiden. – Gishu

-1

Tun Sie das einfach.

class BaseDocument 
{ 
    public DocPath{get; set;} 
    public virtual DocContent{get; set;} 
} 

class DerviedDocument: BaseDocument 
{ 
    public override DocContent 
    { 
     get { return null; } 
     set { } 
    }  
} 

Oder

public override DocContent 
{ 
    get { throw new NotImplementedException("Do not use this property!"); } 
    set { throw new NotImplementedException("Do not use this property!"); } 
} 
+0

@Chaos: -1 becuase, was Sie gaben, ist eine Arbeit um, die erste, von denen ich denke, wird nicht funktionieren, obwohl ich nicht sicher bin. Ich habe bereits bessere Workarounds in meiner Frage gepostet. Und das Problem bleibt bestehen, weil die abgeleitete Klasse die Basisklasseneigenschaft "sieht". Meine Frage bezog sich darauf, sie vollständig zu verstecken. – desigeek

+0

Danke für Ihre Kommentare. Ich habe wirklich Schwierigkeiten zu verstehen, warum du das machen willst. – ChaosPandion

0

Ich glaube nicht, gibt es eine gute (oder überhaupt) Weg, dies zu tun. Möglicherweise müssen Sie die Hierarchie auflösen, oder Sie können die DocContent-Eigenschaft aus BaseDocument entfernen und dann zwei separate Klassen aus BaseDocument ableiten, eine, die Ihr aktuelles DerivedDocument ist, und eine andere, die die DocContent-Eigenschaft besitzt.

2

Es klingt so, als wollten Sie absichtlich das Liskov Substitutionsprinzip verletzen. Warum sollte man sich überhaupt mit Unterklassen beschäftigen, wenn es nicht die herkömmliche Vererbungssemantik hat? Mach einfach eine separate Klasse.

1
interface IBaseDocument 
{ 
    string DocPath { get ; set ; } 
    string DocContent { get ; set ; } 
} 

class BaseDocument : IBaseDocument 
{ 
    public string DocPath { get ; set ; } // implement normally 

    private string MyDocContent ; // use this in BaseDocument 
    string IBaseDocument.DocContent // implement explicitly 
    { 
     get { return MyDocContent ; } 
     set { MyDocContent = value ; } 
    } 
} 

class DerviedDocument : BaseDocument 
{ 
    public void Test() 
    { 
     // error: The name 'DocContent' does not exist in the current context 
     Console.WriteLine (DocContent) ; 
    } 
} 
+0

+1: Schöne Lösung. –

+3

Das einzige Problem mit diesem Ansatz ist, dass Sie, wenn Sie DerivedDocument auf ein IBaseDocument (das ist eine sichere Cast seit es inhertis von BaseDocument, die IBaseDocument implementiert) werfen, jetzt DocContent sehen können. – BFree

3

Sie können es leicht tun, wenn Sie in verschiedenen Baugruppen/Projekte BaseDocument und DerivedDocument mit nichts ausmacht.

Machen Sie DocContent intern. Es wird für alles im selben Projekt wie BaseDocument sichtbar sein, aber für DerivedDocument nicht sichtbar sein, da es sich in einem anderen Projekt befindet. Natürlich müssen Sie BaseDocument veröffentlichen (im Moment haben Sie es als Standard, intern).

Im ersten Projekt:

public class BaseDocument 
{ 
    public string DocPath {get; set;} 
    internal string DocContent {get; set;} 
} 

Im zweiten Projekt, das erste verweist:

class DerivedDocument : FirstProject.BaseDocument 
{ 
    public Test() 
    { 
     DerivedDocument d = new DerivedDocument(); 
     d. //intellisense shows DocPath, but not DocContent 
    } 
} 

Diese Lösung hat den Vorteil, keine Flickschusterei zu sein. Sie können weiterhin die DocContent-Eigenschaft von BaseDocument im BaseDocument-Projekt verwenden. Wenn Sie DocContent in einem anderen Projekt verwenden müssen (getrennt von dem Projekt, in dem sich DerivedDocument befindet), können Sie das InternalsVisibleTo-Attribut verwenden, um DocContent für diese Assembly sichtbar zu machen. (Das ist aber ist meiner Meinung nach ein Klud, obwohl ein sehr handliches in einigen Szenarien.)

+0

+1 das ist sehr nett, aber es bricht alle die Idee einer Klasse, die in einer Datei sein sollte. Nicht die Tatsache, aber es funktioniert. –

+0

Sorry ... es bricht * was * Idee? Es sind zwei separate Klassen, von denen die eine erbt. Ich weiß nicht, von welcher Idee du sprichst. –

0

Eine späte Reaktion, aber es gibt mehrere Möglichkeiten, dies zu tun.

Schönster: Zeigen Sie Base Klasse in einer separaten Assembly und markieren Sie die Eigenschaft DocContent als internal statt public:

class BaseDocument 
{ 
    public string DocPath{get; set;} 
    internal string DocContent{get; set;} //won't be visible outside the assembly 
} 

Oder nutzen attributes die Eigenschaft aus dem Quellcode-Editor zu verstecken:

class BaseDocument 
{ 
    public string DocPath{get; set;} 
    public string DocContent{get; set;} 
} 

class DerviedDocument: BaseDocument 
{ 
    //this class should not get the DocContent property 

    [Browsable(false), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 
    public new string DocContent{ get; set; } 

    public Test() 
    { 
    DerivedDocument d = new DerivedDocument(); 
    d.//intellisense will only show me DocPath 
    //I do not want this class to see the DocContent property 
    } 
} 
Verwandte Themen