派生の禁止

2002年11月24日(日)更新


■万葉集の歌の数

たけち: 今回は「派生の禁止」について勉強しようね。あまり使う機会がない機能なんだけれど、前々回に「抽象的なデータ型、抽象要素」を説明したから、それとペアで覚えておいた方が一応良いからね。まずはこういう例題を見てみるね。XMLデータ側の方は、

※XMLデータ例(長歌)
<?xml version="1.0" encoding="Shift_JIS" ?>
<yomi pno="4089">
高御座 天の日継と すめろきの 神の命の 聞こしをす 国のまほらに 山をしも さはに多みと 百鳥の 来居て鳴く声 春されば 聞きのかなしも いづれをか 別きて偲はむ 卯の花の 咲く月立てば めづらしく 鳴く霍公鳥 あやめぐさ 玉貫くまでに 昼暮らし 夜わたし聞けど 聞くごとに 心つごきて うち嘆き あはれの鳥と 言はぬ時なし </yomi>

 というXMLデータで、XML Schemaの方は次の通りだよ。

※XML Schema(長歌)
<?xml version="1.0" encoding="Shif_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="yomi" type="YomiType" />

<xsd:complexType name="YomiType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="ManyouPoemNumberType" use="required" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:simpleType name="ManyouPoemNumberType">
<xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1" />
    <xsd:maxInclusive value="4516" />
</xsd:restriction>

</xsd:simpleType>

</xsd:schema>

さらら: 歌番号(pno)のデータ型を1〜4516の整数にしているのね。

たけち: そうだね。ここで、そのManyouPoemNumberTypeというデータ型について考えてみよう。

<xsd:simpleType name="ManyouPoemNumberType">
<xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1" />
    <xsd:maxInclusive value="4516" />
</xsd:restriction>

</xsd:simpleType>

たけち: これは整数(xsd:int)を基準型として、それを1〜4516までの数字に制限したものだよね。ここでこの「4516」というのは万葉集の学問の世界では極めて意味のある数字だということはわかるよね。

さらら: えぇ、万葉集の全部の歌の数よね。

たけち: そう。もちろん万葉集の歌の数は数え方によって異なるので、絶対に4516首しかないとは言えないんだけれどね。でも、万葉集を研究している世界では、この数字がIDとしての役割を果たしていて、「この番号なら、この歌」というのが定着しているんだよね。「私は4516首とは認めないから、独自の番号を使う」とかしていたら、もう学問上のコミュニケーションそのものから成り立たないものね。

さらら: そうみたいね。

たけち: そのことから考えると、このManyouPoemNumberTypeをさらに制限(restriction)して新しいデータ型を派生させるような用途って思い浮かぶかな?

さらら: う〜ん、ちょっと考えられないわね。

たけち: まあ強いて言えば、巻ごとの歌番号のデータ型を作ることくらいだけれど、それにしたって、実用的な意味はまずないよね。ということは、逆に考えると、このManyouPoemNumberTypeをさらに制限(restriction)して新しいデータ型を派生させるというのは、まず間違った使い方だと思われるから、そういう危険な行為はあらかじめできないようにしておいた方がいいよね。つまり、そこでそんなことをしたらエラーになるように最初から明示しておくんだ。

たけち


■final="restriction"

さらら: へぇ〜。そんなことができるの? どうやるの?

たけち: これ以上の制限による派生をやめさせたいデータ型定義のところに、final="restriction" という属性を付け加えるんだよ。

※XML Schema: restrictionによる派生の制限 <?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="yomi" type="YomiType" />

<xsd:complexType name="YomiType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="pno" type="ManyouPoemNumberType" use="required" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>

<xsd:simpleType name="ManyouPoemNumberType" final="restriction">
<xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1" />
    <xsd:maxInclusive value="4516" />
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>


■final="union", final="list", final="#all"

さらら: へぇ〜、何かをするための機能ではなくて、できなくするための機能なのね。

たけち: そうだね。そしてさっきは制限(restriction)の場合を見たけれど、単純型の場合、派生は他にもユニオン(union)リスト(list)があったよね。

さらら: あっ、そっ、そうだったわね。。。(^ ^;

さらら

たけち: じゃあ、ユニオン(union)による派生を禁止したい場合とリスト(list)による派生を禁止したい場合の例を次に載せておくね。

さらら: うん。

unionによる派生の禁止(例)
  <xsd:simpleType name="ManyouPoemNumberType" final="union">

listによる派生の禁止(例)
  <xsd:simpleType name="ManyouPoemNumberType" final="list">

さらら: わかりやすいわ。そのまんまね。

たけち: そして制限(restriction)もユニオン(union)もリスト(list)も全部、完全に派生を禁止させたい場合は、次のように書くんだ。

restriction, union, listによる派生の禁止(例)
  <xsd:simpleType name="ManyouPoemNumberType" final="#all">

単純型の派生の制限

さらら: へぇー、じゃあManyouPoemNumberTypeは final="#all" を使った方がいいのかしら。

たけち: そうだねぇ... 例えば以前、反歌(envoy)の例を出したよね。あれはManyouPoemNumberTypeのリスト型を定義したから、 final="#all" はしない方がいいかな。

さらら: あ、そうか..... (^ ^;

さらら

    <?xml version="1.0" encoding="Shift_JIS" ?>
    <yomi pno="4089" envoy="4090 4091 4092">
    高御座 天の日継と すめろきの 神の命の 聞こしをす 国のまほらに 山をしも さはに多みと 百鳥の 来居て鳴く声 春されば 聞きのかなしも いづれをか 別きて偲はむ 卯の花の 咲く月立てば めづらしく 鳴く霍公鳥 あやめぐさ 玉貫くまでに 昼暮らし 夜わたし聞けど 聞くごとに 心つごきて うち嘆き あはれの鳥と 言はぬ時なし
    </yomi>

さらら: というXMLデータの場合は、restrictionだけの禁止の方が良さそうね (^ ^;


■複合型の派生の制限

たけち: 今のは単純型での話だったけれど、複合型でも同様だよ。ただし、単純型の派生が制限(restriction)、ユニオン(union)、リスト(list)の3つであったのに対し、複合型は制限(restriction)と拡張(extension)の2つだから当然、次のいずれかをxsd:complexType要素の属性として使うわけだね。

さらら: あ、なるほど。

たけち

複合型の派生の制限

たけち: ただし、単純型を基準型にして「単純型内容をもった複合型」に拡張する場合は、このfinal属性でいくら禁止にしても派生は禁止できないから気をつけてね。

さらら: どういうこと?

たけち: 例えば次のような場合だよ。次のXML Schemaは派生を禁じたfinal="#all"を使ったManyouPoemNumberTypeを基準型として拡張(extension)でPnoTypeというデータ型を派生させているけれど、これはエラーにならないんだ。

さらら

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="pno" type="PnoType" />

<xsd:complexType name="PnoType">
<xsd:simpleContent>
    <xsd:extension base="ManyouPoemNumberType">
    <xsd:attribute name="color" type="xsd:string" use="required" />
    </xsd:extension>

</xsd:simpleContent>
</xsd:complexType>

<xsd:simpleType name="ManyouPoemNumberType" final="#all">
    <xsd:restriction base="xsd:int">
    <xsd:minInclusive value="1" />
    <xsd:maxInclusive value="4516" />
    </xsd:restriction>
</xsd:simpleType>

</xsd:schema>

さらら: あ、そうか。単純型では制限(restriction)、ユニオン(union)、リスト(list)の3つは禁止できるけれど、拡張(extension)は禁止できないのね (^ ^;

たけち: まあ、こういう単純型に属性を加える派生を禁止することに意味がどれだけあるのか、というのがまず問題だけどね(^^;) でも、こういう派生の禁止はできないことだけは覚えておこうね。

さらら


■Javaの場合.....(^ ^;

さらら: それにしても変わった機能があるのね。

たけち: まあ、このあたりもオブジェクト指向らしい機能だね。

さらら: オブジェクト指向というと、またJava..... あっ (^ ^;

たけち: 一応、Javaの場合でどうなるか見ておこうかなぁ。。。

さらら: え、えぇ(^ ^;) (また薮蛇になってしまったわ...(^ ^;) )

たけち: こんな感じになるかな。

たけち

class J32 {
    public static void main (String args[]) {
        YomiType yomi = new YomiType(8,
            "熟田津に船乗りせむと月待てば潮もかなひぬ今は漕ぎ出でな");
        yomi.display();
    }
}

class YomiType{
    ManyouPoemNumberType pno;
    String pcdata;

    public YomiType(int pno, String pcdata){
        this.pno = new ManyouPoemNumberType(pno);
        this.pcdata = pcdata;
    }

    public void display(){
        System.out.println(pno.output());
        System.out.println(pcdata);
    }
}

final class ManyouPoemNumberType {
    int number;

    public ManyouPoemNumberType(int number){
        if (number >= 1 & number <= 4516 ) {
            this.number = number;
         } else {
             this.number = 0;
        }
    }

    public int output(){
        return number;
    }
}

さらら: またわけがわからない(^^;

たけち: わかる必要がないから、見て欲しいのは最後の方のところだよ。

さらら

final class ManyouPoemNumberType {
    int number;

    public ManyouPoemNumberType(int number){
        if (number >= 1 & number <= 4516 ) {
            this.number = number;
         } else {
             this.number = 0;
        }
    }

    public int output(){
        return number;
    }
}

たけち: ここでManyouPoemNumberTypeは1〜4516の間にない数は0ということにしてしまっているんだけれど、そのManyouPoemNumberTypeは「final class」として定義されている。つまりこれ以上、ManyouPoemNumberTypeから継承(派生)することが禁じられているんだよ。

さらら: ふ〜ん。

たけち: このあたりもオブジェクト指向プログラミング言語に似た機能として覚えておこうね。

さらら: うっ、うん。。(よくわからないけれど(^ ^;) )

たけち: 次回は、派生から少し離れて「名前付きモデルグループのネスト」について勉強することにするね。

さらら: は〜い。

次回は名前付きモデルグループのネストです。...... (^ ^)v

さらら


XMLスキーマのコーナーは、TAKABEさま(XSLTの遊び部屋)の全面的なご協力をいただいて作成しています。