Specript Language Reference rev.0.7.0 www.specript.org

目次 | << 前章 | 次章 >>

4.namespace

namespaceは、JavaのpackageやC++/C#のnamespace同様、定義されるproperty、function、 specの所属する名前空間を規定するものです。

4−1.namespace宣言

namespace宣言は、ソースコードファイルの先頭に記述し、そのソースコードファイル内で 定義されるproperty、function、specの所属するnamespaceを定めます。

【namespace宣言の書式(EBNF)】

<namespace宣言> ::=

"namespace" <namespace名> ( "::" <namespace名> )* ";"

【記述例】
  • 1階層のnamespace
  •     namespace 商品;
        
  • 2階層のnamespace
  •     namespace 商品::在庫;
        

    4−1−1.基本的な説明

    namespace宣言はソースコードファイルの先頭に他の宣言や定義に先立って記述します。 namespace宣言より前に他の宣言や定義があってはいけません。namespace宣言を省略する ことはできません。

    namespace宣言の記述されたソースコードファイルにて定義されたproperty、function、 specは、そのnamespaceに所属することとなります。

    namespace宣言は、予約語はnamespaceですが、記法はJavaのpackage風と なっています。C++/C#のようにnamespace適用範囲を"{"〜"}"で 括ってブロックとするような記述方法ではありません。1つのソースコードファイル内に 定義されるproperty、function、specは、常に同一のnamespaceに属することとなります。

    namespaceは階層を持つことができます。namespaceの階層の区切りはC++風の"::"です。 例えば、namespace "A::B::C"に属するproperty "p"を、 他のnamespace内のプログラムコードから参照するとき、"A::B::C::p"と記述します。 namespaceの階層はプログラムコードの管理上の便宜を図るものですが、本節第3項に 示すような可視範囲決定の根拠にもなります。

    あるnamespaceにて定義されるproperty、function、specの名称たる識別子は、そのnamespace内に おいてproperty、function、spec全体の中でユニークでなければなりません。例えば、 "X"という名称をもつpropertyを定義した場合、同一namespace内で 他に"X"という名称を持つpropertyは定義できません。さらに、同一namespace内で "X"という名称を持つfunctionやspecも定義できません。

    複数のソースコードファイルに同一のnamespace宣言を記述しても構いません。この場合、 前段における識別子のユニーク性については、同一namespaceが宣言される全ての プログラムコード(リンクする全てのソースコードおよび実行可能コード)内にてユニークで なければならないこととなります。

    ただし、後述するprivate修飾子が付与された場合は、定義する識別子は、その識別子が 定義されるソースコードファイル内で定義される全ての識別子、および同一namespaceが 宣言される他のプログラムコードファイル内にて定義されるprivateでない識別子、これらと 重複しなければよいこととなります。言い換えると、他のプログラムコードファイル内で 定義されるprivateな識別子とは重複してよいこととなります。

    namespaceの名称とソースコードファイルのファイル名、namespace階層とソースコードファイルの 格納ディレクトリ階層との間に特に制約や規約はありません。namespace名と ソースコードファイル名は異なっていて構わないし、namespace階層とファイルの 格納ディレクトリ階層が一致していなくても構いません。

    実用上は一定の相関性を持たせるほうが好ましいとはいえます。ただし、次項に示す 複数namespaceが宣言された場合は、そのことを考慮した構成とする必要があります。

    4−1−2.複数namespaceの宣言

    1つのソースコードファイルに複数のnamespace宣言を記述することができます。この場合、 そのソースコードファイル内に定義されるproperty、function、specは、いずれのnamespaceにも 所属する、ということとなります。

    【例】
    [代理店.spec]
        namespace マスター管理::代理店;
        namespace 商品::会計::売掛;
        namespace 商品::在庫::販売管理;
    
        spec 代理店仕様 : { ... }
        
    [納品処理.spec]
        namespace 商品::在庫::販売管理::納品;
    
        property とある代理店 : 商品::在庫::販売管理::代理店仕様 = ... ;
        
    [請求処理.spec]
        namespace 商品::会計::売掛::請求;
    
        property とある代理店 : 商品::会計::売掛::代理店仕様 = ... ;
        

    上記例では、ファイル[代理店.spec]には3つのnamespaceが宣言されています。 [代理店.spec]内で定義されるspec "代理店仕様"は、3つのnamespace、

    "マスター管理::代理店"
    "商品::会計::売掛"
    "商品::在庫::販売管理"

    のいずれにも属することとなります。

    そして、ファイル[納品処理.spec]においては、"代理店仕様"を

    "商品::在庫::販売管理::代理店仕様"

    として使用しています。ファイル[請求処理.spec]では

    "商品::会計::売掛::代理店仕様"

    として使用しています。

    このように、同一のproperty、function、specの定義を、業務の文脈に応じて異なるnamespaceに 所属するものとして、使い分けることができます。

    4−1−3.可視範囲の制御について

    namespaceが異なるproperty、function、specは、デフォルトで可視範囲に制限がかかります。 property、function、specの各定義にpublicprivateといった 修飾子を付与することで可視範囲が変わります。

    以降の各例示ではpropertyの参照について示していますが、functionの呼び出し、 specの使用についても同様です。

    デフォルトの可視範囲

    namespaceに所属するproperty、function、specは、デフォルトでは自namespace内、 および系列下位のnamespaceから可視となります。

    【例】
    [X.spec]
        namespace A;
    
        property pa = ...;
    
        // 自namespace内で定義されるpropertyを参照可能です。
        property q = pa;
    
        // namespace系列下位で定義されるpropertyは参照不可です。
        property r = A::B::pb;  // コンパイル時エラー
        property s = A::B::C::pc;  // コンパイル時エラー
        property t = A::B2::pb2;  // コンパイル時エラー
        
    [Y.spec]
        namespace A::B;
    
        property pb = ...;
    
        // namespace系列上位で定義されるpropertyが参照可能です。
        property q = A::pa;
    
        // namespace系列下位で定義されるpropertyは参照不可です。
        property r = A::B::C::pc;  // コンパイル時エラー
        
    [Z.spec]
        namespace A::B::C;
    
        property pc = ...;
    
        // namespace系列上位で定義されるpropertyが参照可能です。
        property q = A::pa;
        property r = A::B::pb;
        
    [W.spec]
        namespace A::B2;
    
        property pb2 = ...;
    
        // namespace系列上位で定義されるpropertyが参照可能です。
        property q = A::pa;
    
        // 他系列で定義されるpropertyは参照できません。
        property r = A::B1::pb1;  // コンパイル時エラー
        

    private修飾子が付く場合の可視範囲

    property、function、specの各定義にprivate修飾子を付与すると、 自ソースコードファイル内でのみ可視となり、系列下位のnamespaceや、同一namespaceでも 他のファイルからは不可視となります。

    Specriptにおけるprivateは、specの要素が他spec等からprivateである ということではなく、あるソースコードファイルに定義されるproperty、function、 specが、他ファイルからprivateであることを表します。
    【例】
    [X.spec]
        namespace A;
    
        // private修飾子が付いています。
        private property pa = ...;
    
        // privateでも自ファイル内では参照可能です。
        property q = pa;
        
    [Y.spec]
        namespace A::B;
    
        // privateなのでnamespace系列上位で定義されるpropertyでも参照不可です。
        property r = A::pa;  // コンパイル時エラー
        
    [Z.spec]
        namespace A;
    
        // "pa"は同一namespaceですが、privateなので、ファイルが異なる場合は参照不可です。
        property s = pa;  // コンパイル時エラー
        

    public修飾子が付く場合の可視範囲

    property、function、specの各定義にpublic修飾子を付与すると、他系列の namespaceを含む全てのnamespace、全てのファイルから可視となります。

    【例】
    [X.spec]
        namespace A;
    
        // namespace系列下位で定義されるpropertyもpublicなので参照可です。
        property q = A::B1::pb1;
        property r = A::B2::pb2;
        
    [Y.spec]
        namespace A::B1;
    
        // publicです。
        public property pb1 = ...;
        
    [Z.spec]
        namespace A::B2;
    
        // publicです。
        public property pb2 = ...;
    
        // "A::B1::pb1"はpublicなので他系列からも参照可です。
        property q = A::B1::pb1;
        

    4−2.alias定義

    他namespaceに属するproperty、function、specを参照、呼び出し、使用するとき、 namespace付きの ‘フルネーム’で記述しなければなりませんが、alias定義を行うと、 定義されたnamespaceの(より短い)別名を用いてproperty、function、specの参照、 呼び出し、使用ができます。

    【alias定義の書式(EBNF)】

    <alias定義> ::=

    "alias" <alias名> ":" <namespace名> ( "::" <namespace名> )* ";"

    【記述例】
        alias 在庫 : 商品::在庫;
        

    alias定義は、各ソースコードファイルの先頭、namespace宣言の後に複数個記述できます。

    【例】
    [X.spec]
        namespace A::B::C;
    
        public property p = 3;
        
    [Y.spec]
        namespace D::E::F;
    
        // namespace "A::B::C"の別名"C"を定義します。
        alias C : A::B::C;
    
        // "p"参照時、"A::B::C::p"ではなくalias定義された別名を用いて"C::p"と記述しています。
        property q = C::p;  // q == 3となります。
        

    aliasによるnamespaceの別名定義は、それが記述されたソースコードファイル内でのみ有効です。

    複数個のaliasを定義するとき、同じ別名を定義しようとするとコンパイル時エラーとなります。

    【例】
    [X.spec]
        namespace X;
    
        // 同一の別名を定義しようとするとコンパイル時エラーとなります。
        alias A : A::B::C;
        alias A : A::B;  // コンパイル時エラー
        

    alias定義された別名が本来のnamespace名と衝突しているとき、常に別名が優先されます。

    【例】
    [X.spec]
        namespace A::B::C;
    
        public property p = 3;
        
    [Y.spec]
        namespace C;
    
        public property p = 4;
        
    [Z.spec]
        namespace D;
    
        alias C : A::B::C;
    
        // "C::p"は、alias定義が優先されnamesapce "A::B::C"の方の"p"が参照されます。
        property q = C::p;  // q == 3となります。
        

    別名に階層を持たせることはできません。

    【例】
        // 定義する別名に階層は持たせられません。
        alias X::Y : A::B::C::D;  // コンパイル時エラー
        

    目次 | << 前章 | 次章 >>


    (c)2007-2008, Specript Development Team Last Updated: 2008-03-06