Firme (F#)

Un file della firma contiene informazioni sulle firme pubbliche di un set di elementi di programma F#, ad esempio tipi, spazi dei nomi e moduli.Tale file può essere utilizzato per specificare l'accessibilità di questi elementi di programma.

Note

Per ogni file di codice F#, è disponibile un file della firma, ovvero un file con lo stesso nome del file di codice ma con estensione fsi anziché fs.I file della firma possono anche essere aggiunti alla riga di comando di compilazione se si utilizza direttamente la riga di comando.Per distinguere tra file di codice e file della firma, i file di codice vengono talvolta definiti file di implementazione.In un progetto, il file di firma deve precedere il file di codice associato.

Un file della firma descrive gli spazi dei nomi, i moduli, i tipi e i membri nel file di implementazione corrispondente.Le informazioni in un file della firma possono essere utilizzate per specificare a quali parti del codice nel file di implementazione corrispondente è possibile accedere dal codice esterno al file di implementazione e quali parti sono interne al file di implementazione.Gli spazi dei nomi, i moduli e i tipi inclusi nel file della firma devono essere un sottoinsieme degli spazi dei nomi, dei moduli e dei tipi inclusi nel file di implementazione.Con alcune eccezioni illustrate più avanti in questo argomento, gli elementi del linguaggio che non sono elencati nel file della firma sono considerati elementi privati del file di implementazione.Se nel progetto o nella riga di comando non viene trovato alcun file della firma, viene utilizzata l'accessibilità predefinita.

Per ulteriori informazioni sull'accessibilità predefinita, vedere Controllo di accesso (F#).

In un file della firma non si ripetono la definizione dei tipi e le implementazioni di ogni metodo o funzione.Si utilizza invece la firma per ogni metodo e funzione, che serve come specifica completa delle funzionalità implementate da un frammento di uno spazio dei nomi o un modulo.La sintassi per una firma del tipo corrisponde a quella utilizzata nelle dichiarazioni di metodi astratti nelle interfacce e nelle classi astratte e viene mostrata anche da IntelliSense e dall'interprete F#, fsi.exe, quando viene visualizzato l'input compilato correttamente.

Se nella firma del tipo non sono presenti informazioni sufficienti per indicare se un tipo è sealed o se è un tipo di interfaccia, è necessario aggiungere un attributo che indica la natura del tipo al compilatore.Gli attributi utilizzati a questo scopo sono descritti nella tabella seguente.

Attributo

Descrizione

[<Sealed>]

Per un tipo che non dispone di membri astratti o che non deve essere esteso.

[<Interface>]

Per un tipo che consiste in un'interfaccia.

Se gli attributi non sono coerenti tra la firma e la dichiarazione nel file di implementazione, viene generato un errore dal compilatore.

Utilizzare la parola chiave val per creare una firma per un valore o un valore di funzione.La parola chiave type introduce una firma del tipo.

È possibile generare un file della firma utilizzando l'opzione del compilatore --sig.In genere, i file con estensione fsi non si scrivono manualmente.Questi file vengono invece generati utilizzando il compilatore, quindi vengono aggiunti al progetto, se uno è disponibile, e vengono modificati rimuovendo metodi e funzioni a cui non si desidera consentire l'accesso.

Vi sono diverse regole per le firme del tipo:

  • Le abbreviazioni dei tipi in un file di implementazione non devono corrispondere un tipo senza un'abbreviazione in un file di firma.

  • I record e le unioni discriminate devono esporre tutti i campi e i costruttori o nessuno di essi e l'ordine nella firma deve corrispondere a quello nel file di implementazione.Le classi possono rivelare tutti i campi e i metodi nella firma oppure solo alcuni di essi o nessuno.

  • Le classi e le strutture che dispongono di costruttori devono esporre le dichiarazioni delle relative classi di base (dichiarazione inherits).Le classi e le strutture che dispongono di costruttori devono inoltre esporre tutte le dichiarazioni di interfacce e metodi astratti.

  • I tipi di interfaccia devono rivelare tutti i relativi metodi e interfacce.

Le regole per le firme dei valori sono le seguenti:

  • I modificatori per l'accessibilità (public, internal e così via) e i modificatori inline e mutable nella firma devono corrispondere a quelli nell'implementazione.

  • Il numero di parametri di tipo generico (derivati in modo implicito o dichiarati in modo esplicito) deve corrispondere e i tipi e i vincoli di tipo nei parametri di tipo generico devono corrispondere.

  • Se viene utilizzato l'attributo Literal, deve apparire sia nella firma che nel'implementazione e lo stesso valore letterale deve essere utilizzato in entrambi i casi.

  • Il modello dei parametri (anche noto come grado) delle firme e delle implementazioni deve essere coerente.

Nell'esempio di codice seguente viene illustrato un esempio di file della firma che dispone di spazio dei nomi, modulo, valore della funzione e firme del tipo insieme agli attributi appropriati.Viene inoltre illustrato il file di implementazione corrispondente.

// Module1.fsi

namespace Library1
  module Module1 = 
    val function1 : int -> int
    type Type1 =
        new : unit -> Type1
        member method1 : unit -> unit
        member method2 : unit -> unit

    [<Sealed>]
    type Type2 = 
        new : unit -> Type2
        member method1 : unit -> unit
        member method2 : unit -> unit

    [<Interface>]
    type InterfaceType1 =  
        abstract member method1 : int -> int
        abstract member method2 : string -> unit

Nel codice seguente viene visualizzato il file di implementazione.

namespace Library1

module Module1 =

    let function1 x = x + 1


    type Type1() =
        member type1.method1() =
            printfn "test1.method1"
        member type1.method2() =
            printfn "test1.method2"


    [<Sealed>]
    type Type2() =
        member type2.method1() =
            printfn "test1.method1"
        member type1.method2() =
            printfn "test1.method2"

    [<Interface>]
    type InterfaceType1 =
        abstract member method1 : int -> int
        abstract member method2 : string -> unit

Vedere anche

Concetti

Controllo di accesso (F#)

Altre risorse

Riferimenti per il linguaggio F#

Opzioni del compilatore (F#)