继承和多肽是面向对象编程的一部分
可以有效的提高代码的复用率,少写代码,代码修改维护方便

AS也是一种面向对象的脚本语言,有非常多的封装内容,自然也有继承与多肽
实际上,继承与多肽是Sven Co-op脚本中非常重要的一个内容


继承

Sven Co-op使用的继承特征

  1. 单继承,一个子类最多继承一个父类,但是可以使用接口实现多态,并且提供混合类实现代码的复用和默认方法
  2. 继承具有传递性,B继承A,C继承B,那么A的方法在C中也能找到
  3. 基类派生出的子类具有可拓展性
  4. 所有类方法都是虚拟的(virtual),无需手动指定

列如

class CFood
{
    //这是父类
    void Delicious()
    {
        //我是一个父类的方法!
    }
}

class CPaddy : CFood
{
    //这是子类,父类是CFood
    void Green()
    {
        //可以使用父类的方法!
        Delicious();
    }
}

class CRice : CPaddy
{
    //这是二重继承子类,父类是CPaddy
    void Feed()
    {
        //既可以使用爷爷的方法!又可以使用爸爸的方法!
        Delicious();
        Green();
    }
}

构造方法

每一个类都有构造方法,如果不显示写的话,默认的是无参构造方法
但是为了避免各种神必情况和AS解释器日常智障,虽然子类不会继承父类的构造方法,也请在父类里写上无参构造
列如

class CFather
{
    //显式写了父类的有参构造方法,此时不会默认加载无参构造
    CFather(string&in _str)
    {
        g_Game.AlertMessage( at_console, "快看,我有一个有参构造方法,参数是%a", _str );
    }
}

class CSon : CFather
{
    //并不会继承父类的构造函数
    CSon()
    {
        g_Game.AlertMessage( at_console, "这是一个无参构造方法!" );
        super("可以使用super关键词调用父类的非默认构造函数");
        //这样会报错
        super();
    }
}
void PluginInit()
{
    //直接调用父类的构造函数会报错!
    CSon("这样会报错");
}

类的转化

任何从父类派生出的子类均可以隐式转化成父类,而不需要任何显式标记
但是父类无法隐式转化为子类,必须进行显式转化
列如

class CAnimal
{
    //父类
}
class CDog : CAnimal
{
    //子类
}

void DoSomeThing()
{
    CAnimal @animal;
    CDog @dog;

    //正常使用构造方法为句柄赋值
    @animal = CAnimal();
    //可行,此时Dog()匿名变量将会被隐式转化为CAnimal并给句柄赋值
    @animal = CDog();

    //不行,无法将Animal()隐式转化为CDog,将会出现编译错误
    @dog = CAnimal();
    //可
    @dog = CDog();

    //可行,存在将dog隐式转化为CAnimal
    @animal = dog;
    //坏,无法将animal隐式转化为CDog,将会出现编译错误
    @dog = animal;

    //可行,此时存在将animal显式强制转化的过程
    //但若此时animal并不是CDog的实列将会使得显式转化结果返回值为null
    @dog = cast<CDog>(animal);
}

最终类

可以将一个类以final标记以防止其被继承,也可以将类方法标记为final防止其被重写
列如

//整体无法被继承的类
final class CFinal
{
    //爷就是最后的命运之子!
}
class CNiceTry : CFinal
{
    //无法继承! 编译器将会报错!
}

//带有单个final方法的类
class CMean
{
    void Iron() final
    {
        //这是一个不能被重写的方法
    }
    void Wood()
    {
        //这个可以
    }
}

抽象类

可以将一个类以abstract进行标记,此时这个类将无法实列化,但是可以进行继承,通常用于父类
但是
as无法做到方法的抽象化,所以即使是抽象类方法也必须有实现

abstract class CDaddy
{
    void Method()
    {
        //必须进行方法的实现
    }
    //无实现是不被允许的
    abstract void Negative()
}

class CBaby : CDaddy
{
    //可继承抽象类
}

void DoSomeThing()
{
    //无法实例化抽象类,将会报错
    CDaddy();
    //需实例化抽象的继承类
    CBaby();
}

多态

重写

将子类中的方法以override标记时,将会重写覆盖父类中的方法

class CVehicle
{
    void Beep()
    {

    }
    void Beep(float pitch)
    {

    }
    void Beep(Vector where) final
    {

    }
}

class CCar : CVehicle
{
    void Beep() override
    {
        //可,父类中有相应的方法
    }
    void Beep(int pitch) override
    {
        //不可,父类中没有相应的方法
    }
    void Beep(Vector where) override
    {
        //不可,父类中该方法被标记为final
    }
}

混合类

由于AS是单继承的,有时可能需要在多个类中实现相同的代码,此时可使用混合类

mixin class CMixin
{
    int a;
    void Method()
    {
        a++;
    }
}
//将mixin类包含到该类中以接收方法和属性
class CGoodThing : CMixin
{
    int OtherMethod()
    {
        Method();
        return a;
    }
}

在类中已经声明的属性和方法将不会包含在内
可以以此使用混合类提供默认实现

mixin class CDaddy
{
    void Happy()
    {
        g_Game.AlertMessage( at_console, "很开心" );
    }
    void Anger()
    {
        //注意mixin中没有Health属性
        Health--;
    }
}
class CBaby : CDaddy
{
    //这样会重写混合类提供的默认方法
    void Happy()
    {
        g_Game.AlertMessage( at_console, "这超好" );
    }
    //此时才声明了Anger()方法使用的属性
    int Health;
}

混合类将会覆盖从父类继承的方法,但是混合类无法覆盖从父类继承的属性

mixin class CEngine
{
    void ZooZooZoo()
    {
        //混合类方法
        g_Game.AlertMessage( at_console, "超大声" );
    }
    //混合类属性
    int oilValue;
}
class CCar
{
    void ZooZooZoo()
    {
        //父类方法
        g_Game.AlertMessage( at_console, "大声" );
    }
    //父类属性
    float oilValue;
}
class CBenz : CCar, CEngine
{
    void Start()
    {
        //将输出超大声
        ZooZooZoo();
        //将输出float
        g_Game.AlertMessage( at_console, typeof(oilValue) );
    }
}

接口

接口的工作方式类似于合同,保证继承接口的子类必须实现接口中声明的方法

//声明一个接口
interface IValve
{
    void Open();
}
//接口实现类
class CPipe : IValve
{
    void Open()
    {
        //实现接口的方法
    }
}

一个类可以实现多个接口,用逗号分隔即可

interface IGasC
{
    void Fire();
}
interface IMass
{
    void Electron();
}
class CGCMS : IGasC, IMass
{
    void Fire()
    {
        //做点什么....
    }
    void Electron()
    {
        //做点什么....
    }
}

混合类的接口

混合类可以继承接口,此时接口的实现可以由混合类提供默认方法,也可以留给子类实现
混合类不能从其他类继承

interface ILeg
{
    void Run();
    void Walk();
}
mixin class CBody : ILeg
{
    void Run()
    {
        g_Game.AlertMessage( at_console, "快跑,阿甘,快跑");
    }
    //混合类实现了Run(),将Walk()留给子类实现
}
class CPerson : CBody
{
    //CBody已经提供了默认方法Run(),无需再次实现
    //但↑是↓Walk()还空着,子类必须实现
    void Walk()
    {
        g_Game.AlertMessage( at_console, "附近走走,找点有趣的东西");
    }
}

其他注意


AS中的类和类中的方法默认都是公开的(public),需要对外隐藏需自行添加privateprotected标记


混合类实质是在子类进行编译前将混合类中所有内容复制进入子类,不属于多继承


Sven Co-op所带的基类可以在游戏中使用as_scriptbaseclasses查看,查看前确保developer大于或等于1‘


Sven Co-op自带的基类👇
(超长警告)

abstract class ScriptBaseEntity : ScriptClassInterface
{
    ScriptBaseEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBaseEntity@ m_pSelf;
    CBaseEntity@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBaseEntity>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BaseEntity@ m_pBaseClass;
    BaseEntity@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BaseEntity>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBaseAnimating : ScriptClassInterface
{
    ScriptBaseAnimating()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBaseAnimating@ m_pSelf;
    CBaseAnimating@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBaseAnimating>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BaseEntity@ m_pBaseClass;
    BaseEntity@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BaseEntity>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBaseMonsterEntity : ScriptClassInterface
{
    ScriptBaseMonsterEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBaseMonster@ m_pSelf;
    CBaseMonster@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBaseMonster>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BaseMonster@ m_pBaseClass;
    BaseMonster@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BaseMonster>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
    array<ScriptSchedule@>@ m_Schedules;
    Schedule@ ScheduleFromName(const string& in szName)
    {
        for (uint uiIndex = 0; uiIndex < m_Schedules.length(); ++uiIndex)
        {
            ScriptSchedule@ pSchedule = @m_Schedules[uiIndex];
            if (pSchedule.szName() == szName)
                return pSchedule;
        }
        return BaseClass.ScheduleFromName(szName);
    }
}

abstract class ScriptBaseTankEntity : ScriptClassInterface
{
    ScriptBaseTankEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBaseTank@ m_pSelf;
    CBaseTank@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBaseTank>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BaseTank@ m_pBaseClass;
    BaseTank@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BaseTank>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBasePlayerItemEntity : ScriptClassInterface
{
    ScriptBasePlayerItemEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBasePlayerItem@ m_pSelf;
    CBasePlayerItem@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBasePlayerItem>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BasePlayerItem@ m_pBaseClass;
    BasePlayerItem@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BasePlayerItem>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBasePlayerWeaponEntity : ScriptClassInterface
{
    ScriptBasePlayerWeaponEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBasePlayerWeapon@ m_pSelf;
    CBasePlayerWeapon@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBasePlayerWeapon>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BasePlayerWeapon@ m_pBaseClass;
    BasePlayerWeapon@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BasePlayerWeapon>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBaseItemEntity : ScriptClassInterface
{
    ScriptBaseItemEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CItem@ m_pSelf;
    CItem@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CItem>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BaseItem@ m_pBaseClass;
    BaseItem@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BaseItem>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}

abstract class ScriptBasePlayerAmmoEntity : ScriptClassInterface
{
    ScriptBasePlayerAmmoEntity()
    {
        @m_pSelf = null;
        @m_pPev = null;
    }
    private CBasePlayerAmmo@ m_pSelf;
    CBasePlayerAmmo@ self
    {
        get const { return @m_pSelf; }
    }
    void SetSelf(CBaseEntity@ pValue) final
    {
        if( this.m_pSelf !is null )
             return;
        @this.m_pSelf = cast<CBasePlayerAmmo>(@pValue);
    }
    private entvars_t@ m_pPev;
    entvars_t@ pev
    {
        get const { return @m_pPev; }
    }
    void SetPev(entvars_t@ pValue) final
    {
        if( this.m_pPev !is null )
             return;
        @this.m_pPev = cast<entvars_t>(@pValue);
    }
    private BasePlayerAmmo@ m_pBaseClass;
    BasePlayerAmmo@ BaseClass
    {
        get const { return @m_pBaseClass; }
    }
    void SetBaseClass(BaseEntity@ pValue) final
    {
        if( this.m_pBaseClass !is null )
             return;
        @this.m_pBaseClass = cast<BasePlayerAmmo>(@pValue);
    }
    private CustomEntityCallbackHandler@ m_pCallbackHandler;
    CustomEntityCallbackHandler@ callback
    {
        get const { return @m_pCallbackHandler; }
    }
    void SetCallbackHandler(CustomEntityCallbackHandler@ pValue) final
    {
        if( this.m_pCallbackHandler !is null )
             return;
        @this.m_pCallbackHandler = cast<CustomEntityCallbackHandler>(@pValue);
    }
    void SetThink(ThinkFunction@ pFunction) final
    {
        callback.SetThinkFunction(pFunction);
    }
    void SetTouch(TouchFunction@ pFunction) final
    {
        callback.SetTouchFunction(pFunction);
    }
    void SetBlocked(BlockedFunction@ pFunction) final
    {
        callback.SetBlockedFunction(pFunction);
    }
    void SetUse(UseFunction@ pFunction) final
    {
        callback.SetUseFunction(pFunction);
    }
}
Categories: 教程合集

Dr.Abc

I ❤ Owl

订阅
提醒
guest

1 评论
最新
最旧 得票最多
Inline Feedbacks
View all comments
M0N5T3R_null
管理员
2020年4月4日 下午5:13

abc nb!

1
0
Would love your thoughts, please comment.x