Unity游戏开发学习之封装,继承,多态
面试点:
封装,继承,多态
值和引用类型的区别
什么是抽象类
什么是接口
抽象和接口的区别
什么是委托
重写和重载的区别
封装,继承,多态
封装:
将类里面的成员变量的方法私有化,如果外界要访问,向外界提供一个统一访问的方法
比如:
public class Person
{
private int age;
public void SetAge(int value)
{
if(value<0&&value<100)
{ 这里就叫做封装
age = value;
}
}
}
变量尽量写成私有,不知道是公开还是私有,也写成私有,如果外界要访问尽量不要直接写成public,写成public是为了方便和展示到unity属性面板上,正常状态下,我们的首选都是私有的,如果外界要访问,我们就给他一个Set方法,如果外界要获得,可以给他一个Get方法
public class Person
{
private int age;
public void SetAge(int value)
{
if(value<0&&value<100)
{ 这里就叫做封装
age = value;
}
}
public int GetAge()
{
return age;
}
}
虽然写了很多,但是其实还是操作age这一个变量,但安全性会提高
因为这种需求太多了,所哟C#提供了属性
public int Age
{
set; 这个就叫做属性
get;
}
如果外界不需要set我们可以只写一个get,如果外界不需要get我们可以只写一个set。
对于属性和上面的方法来说,都叫做封装.
我们刚才举例了将类里面成员进行封装的方法,类里面的方法也可以进行封装,我们来举例说明
比如:
private void Eat(int age)
{
Console.WriteLine(“我的年龄是”+age):
}
这个时候我们可以在这个方法的内部调用这个方法,但是我们不希望把他改成public,因为如果我对外界提供了public方法以后,那么实际上我的age已经有了,如果外界直接调用这个方法,,那么外界就可以给我传进来一个age,造成修改了age.
我们可以这样写:
将刚才的方法写成private ,然后写一个新的方法:
public void NewFunc() //外界专门访问的方法
{
Eat(age);
}
private void Eat(int age)
{
Console.WriteLine(“我的年龄是”+age):
}
这样做的好处是,我不会把参数暴露给外界,外界将不能修改age。
写一个方法,我们发现这个方法有很多参数,但有一些参数我们是不希望暴露给外界的,再写一个方法不给他参数,然后我们将这个方法暴露给外界写成public,这样就是一个对方法的封装
在C#中,是谁在帮助我们封装,其实就是前面的这些关键字,private和public.
封装的好处是什么?
减少耦合(其实就是两个对象之间调用的关系更加简单了)。
防止外界进行修改。
实现方式:
编写public方法进行私有变量或方法的封装
属性
继承:
创建新的类(派生类/子类),可以继承现有类(基类/父类)的特性,并且还可以进行修改和扩充.
比如说有一个类
public class LaoWang
{
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
后面我们在写一个类
public class XiaoWang : LaoWang
{
}
哪怕这个类里面什么都不写,但是他已经可以用LaoWang里面的变量和方法.
这个就是一个继承
C#的特性是单继承(只能有一个父类,可以有多个继承)
拥有一切父类的特性,可以调用一切父类里面的方法吗?取决于前面的修饰符,public可以调用,如果父类里面的方法或变量为private则不可被调用。
对于protected来说,在子类里面可以正常访问,但在外界不可访问,而public在外界也可以被访问。比如外界拿到了XiaoWang(XiaoWang xw = New XiaoWang();),想要调用xw.Play();
这时,如果LaoWang是protected则不可被调用,public则可以被调用。
protected class LaoWang
{
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public XiaoWang()
{
Play();
}
}
public class LaoWang
{
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public new void Play()
{
Console.WriteLine(“我要打游戏”);
}
}
这样叫做覆盖,但这样其实是不好的,所以一般情况下,你如果想覆盖,不要用new这个关键字,可以用重写
public class LaoWang
{
public virtual void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public override void Play()
{
Console.WriteLine(“我要打游戏”);
}
}
在父类的方法加上virtual,这样就是告诉子类,我这个方法是可以被覆盖的
加上virtual的方法我们叫做虚方法,所有的虚方法是可以被重写的.
有时我们希望保留父类的方法,并且还有自己的方法
public class LaoWang
{
public virtual void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public override void Play()
{
base.Play();
Console.WriteLine(“我要打游戏”);
}
}
可以通过base来保留父类的方法.
public class LaoWang
{
//构造方法(在实例化的时候被调用)
public LaoWang()
{
Console.WriteLinr(“我是老王”);
}
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public XiaoWang()
{
Console.WriteLine(“我是小王”);
}
}
当我们new小王的时候,“我是小王”这句话会打印,“我是老王”这句话会打印吗?
会打印,并且会先调用父类的方法,然后才会调用子类的方法
public class LaoWang
{
//构造方法(在实例化的时候被调用)
public LaoWang()
{
Console.WriteLinr(“我是老王”);
}
public LaoWang(int age)
{
Console.WriteLine(“我是老王,我今年”+age);
}
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public XiaoWang()
{
Console.WriteLine(“我是小王”);
}
public XiaoWang(int age)
{
Console.WriteLine(“我是小王,我今年”+age);
}
}
现在我们使用XiaoWang xw = new XiaoWang(20);
会先调用父类的LaoWang()方法,然后调用XiaoWang(int age)方法,所以无论子类的构造方法写成什么样,他调的永远都是父类默认的构造方法。
如果你希望去调用父类带参数的构造方法,需要使用到下面的方法:
public class LaoWang
{
//构造方法(在实例化的时候被调用)
public LaoWang()
{
Console.WriteLinr(“我是老王”);
}
public LaoWang(int age)
{
Console.WriteLine(“我是老王,我今年”+age);
}
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
}
public class XiaoWang : LaoWang
{
public XiaoWang()
{
Console.WriteLine(“我是小王”);
}
public XiaoWang(int age) : base(age)
{
Console.WriteLine(“我是小王,我今年”+age);
}
}
既然我们说到了重写,那我们就来说一下重载,以此来分辨两个的区别
一个类里面不能同时出现两个同名的方法,但是可以出现同名的方法参数个数是不同的。
public class LaoWang
{
//构造方法(在实例化的时候被调用)
public LaoWang()
{
Console.WriteLinr(“我是老王”);
}
public void Play()
{
Console.WriteLine(“我要去喝酒”);
}
public void Play(string name)
{
}
}
这样的方式就叫做重载
多态:
父类类型可以接收子类对象,以至于调用同样的方法产生不同的结果。
接口也是实现多态的一种方式。
假如现在有一个游戏里面NPC的类
public class NPC
{
public virtual void Say()
{
}
}
这个NPC父类说话我们不实现如何东西,因为我们不会直接去创建NPC,每个NPC都有 不同的说话方式
接下来写两个子类
public class ChaoShen:NPC
{
public override void Say()
{
Console.WriteLine(“超神:123456”);
}
}
public class XiaoBai:NPC
{
public override void Say()
{
Console.WriteLine(“小白:789456”);
}
}
接下来我们都将他俩实例化出来
ChaoShen cs = new ChaoShen();
XiaoBai xb = new XiaoBai();
所谓的多态是什么,多态就是指我们可以用它的父类的变量接收子类的对象,小白和超神的父类都是NPC,所以我们可以这样写:
NPC npc1 = xb;
NPC noc2 = cs;
这个东西就叫做多态
既然他们俩都是npc,就可以把他们俩放在一个数组里,正常情况下,他们俩类型不同,不能放在一个数组里,这时候就应用到多态性了:
NPC[] npcs = new NPC[] {xb.cs};
foreach (NPC npc in npcs)
{
npc.Say();
}
原文链接:https://blog.csdn.net/weixin_41644677/article/details/91905551
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?