找回密码
 立即注册
查看: 525|回复: 9

unity中什么情况下用得上接口,应该怎么理解接口呢?

[复制链接]
发表于 2021-4-2 09:33 | 显示全部楼层 |阅读模式
unity中什么情况下用得上接口,应该怎么理解接口呢?
发表于 2021-4-2 09:36 | 显示全部楼层
接口在C#、JAVA等现代语言中比较常用,它是对面向对象编程的一种很好的补充。
1、单纯使用继承的局限性

现实中的事物从不同角度来看,往往有多种特性。而传统的面向对象思想以继承为基础,有时显得非常死板。
继承的含义是:如果A继承B,那么“A是一种B”。例如人继承动物,则人是一种动物;同理猫也是动物,狗也是动物,海象也是动物。
这个思想看似比较接近现实,但现实中分类往往不止有一个角度,例如同样是狗,它俩就不太像:
如果以 可以揪着毛抓起来 作为分类条件,那么应该这么分,它俩是一类:
它俩是一类:
这么说的话,要不要以 长毛动物 短毛动物 作为基类呢?似乎还是不大对,如果以“是否会抓老鼠”作为判断依据又要重新分类了。
由于继承的方式只能从一个角度形成继承关系,如果需求比较复杂就会捉襟见肘。也有很多语言支持“多重继承”,就是一个类可以有多个基类。
多重继承看似很美好,但工程实践证明这样设计很可能弊大于利。所以Java和C#等工程化的语言都摒弃了多重继承。
2、从特性和功能出发,代替继承的思路

前面的例子太萌了,换个理性一点的例子。如果简单将设备分为输入设备输出设备,可形成下面的设计图:
问题来了,手机是输入设备还是输出设备?
虽然换一种继承思路可能可以解决问题,但从中可以看出“继承”本身是有局限性的。如果我们把需要关心的“功能和特性”列出表来,实际上是这样的:
单纯从一个角度分类,远远不如像这样把功能摊开的好。如果把左边的每个“可XXXX”看做一种接口(接口这个名词翻译得有问题,应当理解为“满足的协议”或“承诺可进行的操作”),接口定义像这样写:
  1.     // 可按下按键的“协议”
  2.     interface IPressButton
  3.     {
  4.         // 按下某个按键
  5.         void Press(int button);
  6.     }
  7.     // 可插USB的“协议”
  8.     interface IUSB
  9.     {
  10.         // 插USB
  11.         void PlugUSB();
  12.     }
复制代码
所有的具体类型,要根据是否满足协议来设计:
  1.     class 键盘 : IPressButton, IUSB
  2.     {
  3.         public void Press(int b)
  4.         {
  5.             Console.WriteLine("按下键盘"+b+"键");
  6.         }
  7.         public void PlugUSB() { }
  8.     }
  9.     class 鼠标 : IPressButton, IUSB
  10.     {
  11.         public void Press(int b)
  12.         {
  13.             Console.WriteLine("按下鼠标"+b+"键");
  14.         }
  15.         public void PlugUSB() { }
  16.     }
  17.     class 显示器 : IPressButton
  18.     {
  19.         public void Press(int b)
  20.         {
  21.             Console.WriteLine("按下显示器"+b+"键");
  22.         }
  23.     }
  24.     class 手机 : IPressButton, IUSB
  25.     {
  26.         public void Press(int b) {
  27.             Console.WriteLine("按下手机"+b+"键");
  28.         }
  29.         public void PlugUSB() { }
  30.     }
复制代码
可以看到,四种物体都可以按下按钮,但是显示器不支持USB(假设这种显示器不支持)。
创建物体的代码没有区别:
  1.             键盘 k1 = new 键盘();
  2.             键盘 k2 = new 键盘();
  3.             鼠标 m1 = new 鼠标();
  4.             手机 h1 = new 手机();
  5.             显示器 tv1 = new 显示器();
  6.             显示器 tv2 = new 显示器();
复制代码
在这种设计下,很多功能的实现方便。
需求1、统一按下所有物体的按键。
  1.             List<IPressButton> list = new List<IPressButton> {
  2.                 k1,k2, m1, h1, tv1, tv2
  3.             };
  4.             // 按下所有物体的按钮
  5.             foreach (IPressButton obj in list)
  6.             {
  7.                 obj.Press(1);
  8.             }
复制代码
需求2、插某个物体的USB接口
  1.             // 插鼠标USB
  2.             IUSB usbDevice = m1;
  3.             usbDevice.PlugUSB();
  4.             // 插手机USB
  5.             usbDevice = h1;
  6.             h1.PlugUSB();
  7.             // 插显示器USB,插不了
  8.             usbDevice = tv2;     // !错误,类型不匹配
复制代码
更多的例子不再列举,相信如果看懂了上面的例子,就知道接口的灵活性体现在哪里了。 :)
3、Unity中是否要使用接口

别忘了其实除了接口和继承,还有另一种很好的扩展类的方法:组合
而且Unity把“组合”的方法推而广之,形成了GameObject - Component体系,也就是组件化设计
前面的例子里,我用了接口变量指代物体。其实在Unity中,还支持用组件来指代物体。至少从游戏开发实践来说,大部分时候组件比接口更为常用。
很多UI框架中大量使用接口,这是UI本身的复杂性决定的。接口在复杂的逻辑架构中也有用武之地。
建议在Unity中一定要优先学好掌握好组件式程序设计的思想,在制作更复杂的系统和框架时,可以考虑使用接口。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-4-2 09:40 | 显示全部楼层
接口使一组不相关的类具有相同的行为。
发表于 2021-4-2 09:42 | 显示全部楼层
我还真就在unity用过接口,组件化的设计过于便捷,导致所谓的设计模式很少有用武之地,所以接口几乎在unity绝迹了。我平时用的最多的是单例模式,也没有用到接口。
当时用到的情况是,用户有个需求,有Ctrl z撤销,Ctrl y前进的功能。我就琢磨了一个接口istep 里面有两个方法,cancel 和do
然后每种数据操作写一个istep实现类,如transformstep,如imagestep。每次用户操作都会把组件原数据和变更的数据new一个类出来,入栈stack<istep>,需要撤销就从栈顶取然后调用cancel,前进就do。
发表于 2021-4-2 09:49 | 显示全部楼层
接口使一组不相关的类具有相同的行为。
这是另一位作者很完美的回答
这句话也可以反过来说,使一组不相关但有相同行为的类,具有同一个称呼。
这个问题其实没必要具体到unity下,但题主既然这样问,我们就具体到unity下,在游戏中举例一个场景
一个mmo游戏中,有角色,有武器,有符文,这些对象都会产生攻击力数值,他们的类肯定不同,返回攻击数值的内部逻辑也不一样,但是从产生攻击数值的角度,他们都是ATKNumberCreater
我这时要算这些相加的总攻击力,我就可以让他们都继承IATKNumberCreater接口都实现getATK()的方法,通过数据结构循环处理相加,获得我想要的总攻击力。


所以说接口是一种以行为为基准的抽象,我们抽象的最终目的是方便代码批量处理他们
发表于 2021-4-2 09:56 | 显示全部楼层
很多情况用接口啊,而且很好用呢!给你个链接
【搬运】C#基础,什么是接口(Interface) UP主: RayGC http://www.bilibili.com/video/BV1KT4y137L3?share_medium=android&share_source=more&bbid=XY510EB5C3716C1AC1DD3118A890A790E9D10&ts=1588074287864
 楼主| 发表于 2021-4-2 10:04 | 显示全部楼层
谢邀,,。
其实应该问面向对象编程过程中,如何理解和使用接口。接口是非常抽象的概念,结合接口的命名习惯一般为I*或者*Able,可以理解为具有某种能力的要求。继承该接口必须具备这种能力,但是能力的实现过程就又实现类来控制了。你可以给自己预设几个理想场景去应用一下,比如设计一个塔防游戏,那所有的塔都具备Attack的能力,就设计一个IAttack接口,声明一个DoAttack的方法,所有的塔都去继承这个接口,实现DoAttack这个方法,具体攻击力,频率就各自实现了。
由于Unity引擎的特点,在项目设计上有些特殊性,会增加你理解需要设计的复杂性,如果感到困惑可以尝试脱离Unity直接在vs之类的环境中来感悟语言及其设计特性。
设计的重要目标之一就是高度抽象下约束实现路径。多态是达成这个目标的主要手段之一。
手机码字,恐有不详,希望可以帮到你。
另外借楼求一枚想做独立游戏的美术小伙伴,感兴趣请私我。
发表于 2021-4-2 10:11 | 显示全部楼层
我也是小白,首先我觉得要区分好接口和抽象类这两个概念,unity中也有好多接口,比如拖动,我自己理解当代码分层较多的时候,比如一个功能,但是功能不确定,这时候就可以用接口了吧。
发表于 2021-4-2 10:15 | 显示全部楼层
使用接口与u不unity没有必然关系。
oop的核心,或者说软件工程的一大追求,就是追求强生命力的软件,当新需求来了时,可以通过添加新模块,而不是修改旧模块的方式解决。
usb接口就是一个很好的现实意义的接口,你可以连接键盘,鼠标,手机,音箱甚至咖啡机,不用管它们具体是什么职能,只需要它有一个usb插头;而它们可以插到电脑,智能电视等各种设备上,只需要它有一个插孔。
只要插头和插孔匹配,就可连接,以实现不同功能。
现实如此,编程也是如此,接口的意义就是“一个规范,万般实现”,使得你在不用改变既有代码的前提下,进行功能扩展。对增加开放,对修改关闭。
现实中还有转接头,将原本不能连接的设备,转换接口之后连接,而设计模式中就有adapter模式,将本不能一起工作的类型,转换接口之后一起工作。
活字代替雕版的意义深远。
接口,就是字面的意思呢。
发表于 2021-4-2 10:22 | 显示全部楼层
我自己理解也相当一般,写下来互相交流吧。
1.c#是不支持多重继承的,如果一个类想实现类似多重继承的效果,只能用接口。此外,如果只是一般的单继承的话,个人觉得直接用类甚至更方便些。
2.在初始写框架的时候,将要做的功能模块的具体功能应接口定义好,实现功能的时候能方便自上而下的实现。
暂时想到这些,想到别的再补充。
3.
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-20 20:35 , Processed in 0.102566 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表