• Unity 游戏框架搭建 2019 (三十九、四十一) 第四章 简介&方法的结构重复问题&泛型:结构复用利器


    第四章 简介

    006tNc79gy1fzfsej80nwj30gb0mcacz.jpg

    方法的结构重复问题

    我们在上一篇正式整理完毕,从这一篇开始,我们要再次进入学习收集示例阶段了。

    那么我们学什么呢?当然是学习设计工具,也就是在上篇中提到的关键知识点。这些关键知识点,大部分来自于 C# 语法。

    不过在此之前,我们先实现一个功能,这个功能是,传入几个数字,随机取出其中一个数字。

    比如传入 1,3,5,7 从这四个数字中随机取出一个数字出来。

    其实现很简单 代码如下:

    using UnityEngine;
    
    namespace QFramework
    {
    	public partial class MathUtil
    	{
    		public static int GetRandomValueFrom(int[] values)
    		{
    			return values[Random.Range(0, values.Length)];
    		}
    	}
    }
    

    传入一个,int 数组,从 int 类型数组中随机取一个数值进行返回。

    用法也很简单,使用代码如下:

    var randomValue = GetRandomValueFrom(new int[] {5, 100, -1, -3, 5});
    

    但是随着时间发展,我们有时候会需要随机获取其他类型值,比如从一个 float 类型的数组中随机取回一个 float 值,或者是从 string 类型的数组中取回一个值。

    难道我们要每个类型都实现一次嘛? 如果都实现一次的话,会增多很多重复结构的代码,注意看这里是重复的结构。

    什么叫重复的结构,以下代码就是三个重复结构的方法。

    public static int GetRandomValueFrom(int[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    
    public static string GetRandomValueFrom(string[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    
    public static float GetRandomValueFrom(float[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    虽然对初学者来说,知道把方法做成工具类已经很不容易了,但是以上这样的代码肯定是不行的。

    所以就要学习新的知识,但是笔者接下来要说的这个知识大家应该很熟悉了。

    就是面试中常问的:面向对象的特性?
    答:封装、继承、多态。

    而我们要用其中的继承特性。

    我们先复习一下继承:B 继承 A,那么 B 对象就可以拥有 A 中的 public、protect 方法和成员变量。
    复习完了。。。

    继承的本质是,什么是什么的问题,比如 B 继承 A,那么我们可以使用 A 变量去接收 B 对象。
    代码如下:

    class A
    {
    }
    
    class B : A
    {
    }
    
    A a = new B();
    

    这样的的代码是没问题的。

    虽然以上代码和多态性有一点关系,不过我们只要记住,父类的变量可以接收子类的实例这个结论就好了。

    那么对我们的问题有什么帮助呢?

    我么再来看下问题代码:

    public static int GetRandomValueFrom(int[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    
    public static string GetRandomValueFrom(string[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    
    public static float GetRandomValueFrom(float[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    int、string、float 如果有一个共同的父类,那么就可以用一个共同的父类,作为参数的类型。

    那么 int、string、float 有没有共同的父类?答案是有的,它们共同继承了 object 类。不止是int、string、float,C# 中的所有类型都继承了 object 类。

    我们有了答案,可以进行更改了,改完的代码如下:

    public static object GetRandomValueFrom(object[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    我们看下使用的代码

    var intRandomValue = (int)GetRandomValueFrom(new int[]{1,2,3});
    var stringRandomValue = (string)GetRandomValueFrom(new string[]{"asdasd","123123"});
    var floatRandomValue = (float)GetRandomValueFrom(new float[]{ 0.1f,0.2f });
    

    使用的代码虽然比较难看(1.强制类型转换;2.再加上每次传入参数都要构造数组;)

    使用上有一点麻烦,不过还好,我们最起码解决了结构重复的问题,而且我们还复习了一下继承。

    当然除了使用 object 接收,还有更好的方法-使用泛型。之所以先介绍 object ,是因为,笔者在没接触泛型之前,都是这么搞的,这样搞其实还有个问题,就是值类型转引用类型会造成效率问题,不过这些问题下一篇再解决,更重要的是,我们今天的问题得到了进展,这是很值得开心的。

    泛型:结构复用利器

    在上一篇我们使用 object 解决了方法结构重复的问题,而在文章的尾部又提了一下更好的方法,就是泛型。

    泛型对很多初学者来说是比较高级的概念,这里呢我们顺便复习一下泛型。

    泛型是什么呢?对于方法来说,方法结构中的部分或全部类型都可以先不进行定义,而是到调用方法的时候再去定义。

    我们的 GetRandomValue 的目前代码如下 :

    public static object GetRandomValueFrom(object[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    测试代码如下:

    var intRandomValue = (int)GetRandomValueFrom(new int[]{1,2,3});
    var stringRandomValue = (string)GetRandomValueFrom(new string[]{"asdasd","123123"});
    var floatRandomValue = (float)GetRandomValueFrom(new float[]{ 0.1f,0.2f });
    

    将 object 改成泛型后如下:

    public static T GetRandomValueFrom<T>(T[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    测试代码如下:

    var intRandomValue = GetRandomValueFrom(new int[]{1,2,3});
    var stringRandomValue = GetRandomValueFrom(new string[]{"asdasd","123123"});
    var floatRandomValue = GetRandomValueFrom(new float[]{ 0.1f,0.2f });
    

    从测试代码中可以比较出来,使用泛型之后的代码确实好用了很多。

    大家思考下泛型是不是这样的?结构中的部分或全部类型都可以先不进行定义,而是到调用的时候再去定义。

    我们有收获了一个法宝泛型。要说方法是逻辑上的复用,那么泛型就是结构上的复用。两大复用法宝。

    关于泛型就先介绍到这里,我们以后还会遇到使用泛型的时候的。

    在看下当前的测试代码:

    var intRandomValue = GetRandomValueFrom(new int[]{1,2,3});
    var stringRandomValue = GetRandomValueFrom(new string[]{"asdasd","123123"});
    var floatRandomValue = GetRandomValueFrom(new float[]{ 0.1f,0.2f });
    

    目前比较麻烦的是数组构造代码了。

    这个也是有办法搞定的。我们把方法的实现改成如下:

    public static T GetRandomValueFrom<T>(params T[] values)
    {
    	return values[Random.Range(0, values.Length)];
    }
    

    大家注意下,参数前边加上了一个 params 关键字。这个是什么意思呢?
    意思是 GetRandomValueFrom 可以传任意数量的参数。

    我们先看下测试代码,测试代码呢其实可以改成如下:

    var intRandomValue = GetRandomValueFrom(1, 2, 3);
    var stringRandomValue = GetRandomValueFrom("asdasd", "123123");
    var floatRandomValue = GetRandomValueFrom(0.1f, 0.2f);
    

    是不是清爽了很多?这就是 params 的用法。

    而通过 params 修饰的 values 参数来说,如果传入的是一个数组,那么 values 本身就是这个数组,如果传入的是若干个值,那么 values 中就包含了这若干个值。

    总结一句话,就是可以传一整个数组,也可以传若干个参数,设计得非常人性化。

    到此呢,我们的第九个示例就已经非常完善了。

    全部代码如下:

    using UnityEngine;
    
    namespace QFramework
    {
    	public partial class MathUtil
    	{
    #if UNITY_EDITOR
    		[UnityEditor.MenuItem("QFramework/9.从若干个值中随机取出一个值", false, 10)]
    #endif
    		private static void GetRandomValueFromMenuClicked()
    		{
    			Debug.Log(GetRandomValueFrom(1, 2, 3));
    			Debug.Log(GetRandomValueFrom("asdasd", "123123"));
    			Debug.Log(GetRandomValueFrom(0.1f, 0.2f));
    		}
    
    		public static T GetRandomValueFrom<T>(params T[] values)
    		{
    			return values[Random.Range(0, values.Length)];
    		}
    	}
    }
    

    代码执行结果如下:
    006tNc79gy1fzfsfiotsuj30e609iwf7.jpg

    编译之后菜单如下006tNc79gy1fzfsfm17ahj30ia0cmdmz.jpg

    目录结构如下
    006tNc79gy1fzfsfo9rylj30jm0ccwg7.jpg

    我们进行一次导出,这次导出就正常导出就好。

    今天的内容就到这里,我们下一篇再见,拜拜~。

    转载请注明地址:凉鞋的笔记:liangxiegame.com

    更多内容

  • 相关阅读:
    Android中Services之异步IntentService(二)
    Android服务之Service(其一)
    JPA 2.0 中的动态类型安全查询
    JPA注解参考
    WebService netbeans glassfish
    android ContentProvider
    github
    移动端
    php
    mysql
  • 原文地址:https://www.cnblogs.com/liangxiegame/p/12807382.html
Copyright © 2020-2023  润新知