继承和多肽是面向对象编程的一部分
可以有效的提高代码的复用率,少写代码,代码修改维护方便
AS也是一种面向对象的脚本语言,有非常多的封装内容,自然也有继承与多肽
实际上,继承与多肽是Sven Co-op脚本中非常重要的一个内容
继承
Sven Co-op使用的继承特征
- 单继承,
一个
子类最多继承一个
父类,但是可以使用接口实现多态,并且提供混合类实现代码的复用和默认方法 - 继承具有传递性,B继承A,C继承B,那么A的方法在C中也能找到
- 基类派生出的子类具有可拓展性
- 所有类方法都是虚拟的(
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
),需要对外隐藏需自行添加private
或protected
标记
混合类实质是在子类进行编译前将混合类中所有内容复制进入子类,不属于多继承
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);
}
}
abc nb!