第五章: 基础的继承 (inheritance)

MudOS v21c2

基础 LPC

作者: Descartes of Borg
第一版: 23 april 1993
第二版: 01 july 1993

第五章: 基础的继承 (inheritance)

5.1 回顾

你现在应该了解函式基本的功能. 你应该可以宣告并呼叫一个函式. 另外, 你应该能认识函式定义, 虽然你可能是第一次接触 LPC. 你现在并不见得能定义你自己的函式. 函式是 LPC 物件的基石. 函式中的程式码, 要别的函式呼叫它们的时候才会执行. 呼叫一个函式时, 作出呼叫的函式要给它输入值, 才能执行被呼叫的函式. 被呼叫的函式执行其程式码, 并传回某种资料型态的传回值给呼叫它的函式. 没有传回值的函式属於无传回值 (void) 型态.

仔细看过你自己的工作室程式码之後, 它看起来大概像这样 (视 mudlib 而定):

-----

inherit "/std/room";

void create() {     ::create();
    set_property("light", 2);
    set_property("indoors", 1);
    set("short", "Descartes 的工作室");
    set("long", "此处是 Descartes 工作的地方.\n这里是一个立方体.\n");
    set_exits( ({ "/d/standard/square" }), ({ "square" }) );
}

-----

如果你到目前为止, 所有的课本内容都了解的话, 你应该能认出以下的程式码:

  • 1)  create()  是函式的定义. (嘿 !   他没有宣告它)
  • 2)  它呼叫 set_property() 、set()、set_exits(), 没有一个函式在这段程式码中曾有宣告或定义.
  • 3)  最上面有一行, 不是宣告变数或函式, 也不是函式定义 !
这一章会找出这些问题的解答, 你现在应该脑中应该有这些问题:
  • 1)  为什麽没有宣告 create() ?
  • 2)  为什麽 set_property() 、set() 、set_exits() 已经宣告并定义过了 ?
  • 3)  档案最上面那一行到底是啥东西 ?


5.2 物件导向程式设计 (object oriented programming, OOP)

继承 (inheritance) 是定义真正物件导向程式设计的特性之一. 它让你创造通用的程式码, 能以多种用途用於许多不同的程式中. 一个 mudlib 所作的, 就是创造这些通用的档案 (物件) , 让你用来制造特定物件.

如果你必须把定义前面工作室全部所需要的程式码写出来, 你大概必须要写 1000 行程式码才能得到一个房间所有的功能. 当然, 那根本是浪费磁碟空间. 再者, 这种程式码与玩家和其他房间的互动性很差, 因为每一个创造者都写出自己的函式以作出一个房间的功能. 所以, 你可能使用 query_long() 写出房间的长叙述, 其他的巫师可能使用 long() . 这就是 mudlib 彼此不相容最主要的原因, 因为它们使用不同的物件互动协定.

OOP 克服了这些问题. 前面的工作室中, 你继承已经定义在 "/std/room.c" 档案中的函式. 它拥有普通房间所需要的全部函式定义其中. 当你要制造一个特定的房间, 你拿这个房间档案中定义好的通用函式功能, 并加上你自己的函式 create() 以制造一个独特的房间.


5.3 继承如何作用

你现在大概猜得出来, 这一行:

-----

inherit "/std/room";
-----

让你继承 "std/room.c" 的函式功能. 藉由继承函式功能, 它代表你可以使用 "/std/room.c" 里面已经宣告并定义好的函式. 在 Nightmare Mudlib 中, "/std/room.c" 里面有许多函式, 其中有 set_property()、set()、set_exits() 函式, 都已经宣告并定义过. 在你的 creat() 函式里, 你呼叫那些函式来设定你房间一开始的值. 这些值让你的房间不同於别的房间, 却保留与记忆体中其他房间互动的能力.

实际的写作中, 每一个 mudlib 都不同, 所以要你使用不同一套的标准函式来达到相同的功能. 说明有哪些函式存在和它们是作什麽用的, 已经超出了这本课本的范围. 如果你的 mudlib 有自己详细的说明资料, 你会找到教你如何使用各种继承档案的说明文件以创造物件. 这些说明应该会告诉你有哪些函式、它们需要哪些输入、它们输出的资料型态、以及它们的功能.


5.4 本章总结

本章距离完整解释继承如此复杂的主题还有一大段距离. 本文的目的只是让你能了解如何使用继承来创造你的物件. 以後的课本将对此会有完整的讨论. 现在你
应该已经了解底下几点:
  • 1)  每一个 mudlib 都有一套通用物件库, 有它们自己的通用函式. 创造者透过继承使用它们, 让撰写物件程式码这件工作更轻松, 并与其他物件之间能良好互动.
  • 2)  可被继承的档案里头的函式, 每个 mudlib 都不一样. 你的 mud 里应该有说明文件解释如何使用这些可被继承的档案. 如果你还不知道有哪些函式可用, 那你就没有办法用它们. 任何时候, 都请你特别注意输入和输出的资料型态.
  • 3)  你藉由底下这行继承函式的功能:
  • -----

    inherit "filename";
    -----
     
     filename  是被继承的物件档案名称. 这行放在你程式码的开头.

    注解:

    你可能看到有几处地方有 ::create() 或 ::init() 或 ::reset()  语法. 你现在不需要完全了解这个, 但是应该告诉你一点线索, 知道它到底是什麽. 「::」运算子是一种特殊的方法来呼叫继承物件的函式 (叫做范围解析运算子 scope resolution operator). 例如, 大多数 mud  的 room.c 都有叫做 create()  的函式. 当你继承 room.c 并设定 create() 时, 你所作的事称为超越 (override) room.c 的 create() 函式. 这表示不管任何东西呼叫你房间的 create() , 它会呼叫「你的」版本, 而不是 room.c 里面的那一个. :: 运算子让你能呼叫 room.c 里的 create() 而不是你的 create().

    一个例子:

    -----

    #1

    inherit "/std/room";

    void create() { create(); }

    -----

    -----

    #2

    inherit "/std/room";

    void create() { ::create(); }

    -----

    第一个例子是个恐怖的例子. 当它被载入时, driver 呼叫 create() , 之後 create() 再呼叫 create(), create() 又呼叫 create(), 这时 create() 又呼叫 create()......换句话说, 所有的 create() 就一直呼叫自己直到 driver 侦测到太深的递回 (recursion) 并跳出来.

    第二个例子基本上只是浪费记忆体, 它的功能跟 room.c 没有两样. 对它而言, driver 先呼叫它的 room.c , 然後呼叫 ::create() , 也就是 room.c 里的 create() . 其他的地方就跟 room.c 的功能一样.


    译者: Spock of Final Frontier  98.Jan.25.

    回上一页