I membri accessibili di una classe interna dovrebbero essere anch'essi interni?

3

Sto progettando un set di API per alcune applicazioni su cui sto lavorando. Voglio mantenere lo stile del codice coerente in tutte le classi che scrivo, ma ho scoperto che ci sono alcune incoerenze che sto introducendo e non so quale sia il modo migliore per risolverle.

Il mio esempio qui è specifico per C # ma questo si applica a qualsiasi lingua con meccanismi simili.

Ci sono alcune classi di cui ho bisogno per scopi di implementazione che non voglio necessariamente esporre nell'API in modo da renderle internal laddove necessario.

Generalmente ciò che farei è progettare la classe come farebbe normalmente (ad esempio, rendere membri public / protected / private ove necessario) e modificare il livello di visibilità della classe stessa in internal . Quindi potrei avere alcune classi che assomigliano a questo:

internal interface IMyItem
{
    ItemSet AddTo(ItemSet set);
}

internal class _SmallItem : IMyItem
{
    private readonly /* parameters */;
    public _SmallItem(/* small item parameters */) { /* ... */ }

    public ItemSet AddTo(ItemSet set) { /* ... */ }
}

internal abstract class _CompositeItem: IMyItem
{
    private readonly /* parameters */;
    public _CompositeItem(/* composite item parameters */) { /* ... */ }

    public abstract object UsefulInformation { get; }
    protected void HelperMethod(/* parameters */) { /* ... */ }
}

internal class _BigItem : _CompositeItem
{
    private readonly /* parameters */;
    public _BigItem(/* big item parameters */) { /* ... */ }

    public override object UsefulInformation
    {
        get { /* ... */ }
    }

    public ItemSet AddTo(ItemSet set) { /* ... */ }
}

In un'altra classe generata (parte di un parser / scanner), esiste una struttura che contiene campi per tutti i possibili valori che può rappresentare. Anche la classe generata è internal , ma ho il controllo sulla visibilità dei membri e ho deciso di renderli anche internal .

internal partial struct ValueType
{
    internal string               String;
    internal ItemSet              ItemSet;
    internal IMyItem              MyItem;
}

internal class TokenValue
{
    internal static int EQ(ItemSetScanner scanner) { /* ... */ }
    internal static int NAME(ItemSetScanner scanner, string value) { /* ... */ }
    internal static int VALUE(ItemSetScanner scanner, string value) { /* ... */ }
    //...
}

Per me, questo sembra strano perché il primo insieme di classi, non ho necessariamente dovuto rendere alcuni membri public , potrebbero essere stati fatti molto bene internal . % membri diinternal di un tipo internal sono accessibili solo internamente comunque, quindi perché renderli public ? Non mi piace l'idea che il modo in cui scrivo le mie classi abbia di cambiare drasticamente (cioè modificare tutti gli usi di public in internal ) solo perché la classe è internal .

Qualche idea su cosa dovrei fare qui?

Ha senso per me che potrei voler rendere alcuni membri di una classe dichiarati public , internal . Ma per me è meno chiaro quando la classe è dichiarata internal .

    
posta Jeff Mercado 11.02.2014 - 18:36
fonte

2 risposte

1

Per quanto riguarda la specifica C #, non vi è alcuna differenza quando si effettua un metodo internal o public fino a quando il tipo che lo contiene è internal . L'unica considerazione potrebbe essere che se dovessi rendere pubblica la classe in futuro, qualunque sia il metodo che probabilmente creerai public , potresti farlo ora. Tuttavia, potresti trovare differenze di opinione anche su questo argomento.

Si tratta di una questione di preferenza da parte tua (e del tuo team) e dubito che potresti persino ottenere un accordo all'interno del tuo team se si tratta di più di pochi sviluppatori, per non parlare di una comunità così ampia.

Inoltre, queste preferenze funzionano bene per ogni nuovo codice scritto, ma per qualsiasi codice esistente, non vi è alcun vantaggio per giustificare il costo di modifica del codice (eccetto per la sanità mentale dello sviluppatore). Ho visto il codice scritto in entrambi gli stili, anche all'interno dello stesso progetto da due diversi sviluppatori.

Per quanto riguarda le specifiche, parti pertinenti della sezione 3.5.2 (pagina 61) di Specifica lingua C # 5.0 afferma quanto segue (e credo che sia lo stesso anche nelle versioni precedenti):

The accessibility domain of a nested member M declared in a type T within a program P is defined as follows (noting that M itself may possibly be a type):

  • If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
  • If the declared accessibility of M is internal, the accessibility domain of M is the intersection of the accessibility domain of T with the program text of P.

Poiché il dominio di accessibilità di T nel tuo caso è internal , quindi il dominio di accessibilità di M è lo stesso indipendentemente dal fatto che sia internal o public .

    
risposta data 21.06.2014 - 00:07
fonte
0

Assicurati che nella tua lingua non ci sia quello che chiamerò "canale laterale" attraverso il quale i consumatori della tua API potrebbero accedere a un membro pubblico di una classe interna, perché se c'è, e lo trovano e lo usano da quel momento, quella parte del tuo codice è "valida" come api pubbliche. Ciò significa che urlano se lo cambi e rimani bloccato sostenendolo.

In Java un esempio di un canale laterale è la riflessione. Gli sviluppatori possono utilizzarlo per ottenere l'accesso ai membri che l'autore di api non ha mai inteso che dovrebbero conoscere.

    
risposta data 05.03.2014 - 19:43
fonte

Leggi altre domande sui tag