前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#-面向对象编程、接口、泛型

C#-面向对象编程、接口、泛型

作者头像
祝你万事顺利
发布2019-05-28 13:39:36
7580
发布2019-05-28 13:39:36
举报
文章被收录于专栏:Unity游戏开发Unity游戏开发
面向对象设计原则:

1 开闭原则:对扩展开放,对修改(old Code)关闭 2 类的单一职责:每个类有且只有一个改变它的原因 3 优先使用组合而非继承: 避免耦合度过高 4 面向接口编程而非面向过程: 定义一个类的时候,先思考对外提供什么功能,定义一个对外的接口 5 依赖倒置: 依赖抽象代码,因为具体实现容易改变 6 接口隔离:尽量定义小而精的接口,类实现多个功能,继承多个接口 7 里式替换:父类可以被子类替换掉 8 迪米特法则 : 类之间数据传递越少越好

C#中抽象类与接口

相同点: 1.可被继承, 不可被实例化,都是抽象的 不同: 1.抽象类可以继承类或接口 接口只能继承接口 2.抽象成员在子类中的实现方式不同,abstract的要用override实现,interface的实现不用 3.抽象类可包含已实现的成员, 接口只能出现抽象的成员 4.接口可以实现多继承,抽象类只能被单继承,基类必须在接口之前 5.接口中的方法必须被子类实现,抽象类中的方法不用,抽象方法必须被实现

面向对象的三大特性:封装,继承,多态

封装:组织代码的过程 继承:对概念和代码的复用 继承中的构造函数:构造函数不被继承,子类创建对象的时候,先调用父类的构造函数,再调用自己的构造函数,在父类没有无参的构造函数的时候,子类通过Base关键字指定调用调用哪个父类的构造函数。 多态:隐藏、重写、重载 隐藏:在子类中使用new关键字实现隐藏父类的方法 重写:父类方法不适用或者父类的抽象方法,子类中必须重写。可以重写的方法:虚方法、重写方法、抽象方法。 虚方法:用virtual修饰的方法,子类中可以不重写,抽象类和抽象方法都是用abstract修饰,抽象方法必须出现在抽象类中,子类必须重写抽象方法。

接口

接口目的为了提高代码的复用性我们用接口来定义行为 定义一组规范的数据结构,C#中为类提供某些功能 接口不能添加Public外的访问修饰符,接口中所有成员默认Public。接口中不能包含字段已实现的方法。只能包含属性、未实现的方法、事件。 命名规范:一般接口的命名以"I"开头 实现方式两种: 隐式实现:通过方法名实现方法,方法前加public 显示实现(少用):通过“接口.方法名”的形式实现。显示实现可以避免二义性,访问显示实现的接口要创建对应接口的类,来进行访问。

代码语言:javascript
复制
namespace 接口
{
    //定义接口: 接口命名以大写I开头 , 后面单词首字母大写
    //接口可以直接声明,但是不能被new
    //接口中的成员也是抽象的
    interface IMyInterface
    {
        void Add(int i, int j);
    }
    //接口是抽象的概念,创建接口对象,需要声明接口new子类
    //接口可以被继承
    //实现接口的方法不需要 override
    class MyClass : IMyInterface
    {
        public void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
    }
    //抽象类,成员可以是非抽象的
    abstract class MyAbstractClass
    {
        public abstract void Add(int i, int j);
        
    }

    class MyClass2 : MyAbstractClass
    {
        public override void Add(int i ,int j)
        {
            Console.WriteLine(i + j);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            IMyInterface myInterface = new MyClass();
            myInterface.Add(2, 2);
        }
    }
}

显式实现接口和隐式实现接口

代码语言:javascript
复制
//定义接口: 接口命名以大写I开头 , 后面单词首字母大写
    //接口可以直接声明,但是不能被new
    //接口中的成员也是抽象的
    interface IMyInterface
    {
        void Cal(int i, int j);
        string Name { get; set; }
        void Print();
    }
    interface ICal
    {
        void Cal(int i, int j);
    }
    //接口是抽象的概念,创建接口对象,需要声明接口new子类
    //接口可以被继承
    //实现接口的方法不需要 override
    
    class MyClass : IMyInterface, ICal
    {
        private string name;
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
        //隐式实现接口
        public void Print()
        {
            Console.WriteLine(Name);
        }
        //显示实现接口
        //想调用显式接口,需要声明父接口才可以调用
        void IMyInterface.Cal(int i, int j)
        {
            Console.WriteLine(i + j);
        }
        void ICal.Cal(int i, int j) {
            Console.WriteLine(i - j);
        }

        public void Cal(int a, int b)
        {
            Console.WriteLine(a * b);
        }
    }
Struct 结构体

我们要复用一些数据时可以使用结构体来直接定义数据的集合

泛型

将类型作为参数,在使用的时候再具体决定 泛型参数可以是多个,一般使用大写的T开头 反省参数一般可以使用在方法 类 委托等

代码语言:javascript
复制
namespace 泛型
{
    class Program
    {
        static void Main(string[] args)
        {
            //泛型 C#2.0 推出的一种新机制 , 简化 面向对象开发代码
            //栈
            MyStack<int> myStack = new MyStack<int>();
            myStack.Push(233);
            myStack.Push(1);
            Console.WriteLine(myStack.Pop());
            Console.WriteLine(myStack.Pop());
        }
    }

    class MyStack<T>
    {
        static int cap = 4;
        T[] intStack = new T[cap];
        static int currentIndex = 0;
        public T Pop()
        {
            currentIndex--;
            return intStack[currentIndex];
        }
        public void Push(T i)
        {            
            if(currentIndex >= intStack.Length)
            {
                cap *= 2;
                T[] newStack = new T[cap];
                for(int j = intStack.Length; j < intStack.Length; j++)
                {
                    newStack[j] = intStack[j];
                }
                intStack = newStack;
            }
            intStack[currentIndex] = i;
            currentIndex ++;
        }
    }
}

第二种写法

代码语言:javascript
复制
//类型: 不安全的栈 会有拆装箱操作
    class MyStack2 {
        public void Push<T>(T t) { } 
    }

进行泛型约束: 约束条件为接口是,将泛型参数类型为接口或者接口的实现类

代码语言:javascript
复制
MyStack2 xixi = new MyStack2();
            xixi.Push<SubCard>(new SubCard());
        }
    }

    class Card
    {

    }
    class SubCard : Card
    {

    }

    //类型: 不安全的栈 会有拆装箱操作
    class MyStack2 {
        //将T约束为某一类型,或其子类型
        public void Push<T>(T t) where T:Card
        { } 
    }

使用接口作为泛型约束的实例 对任意可比较类型数据进行升序排序(冒泡)

代码语言:javascript
复制
class MyClass02 : IComparable
    {
        public int i;
        public int CompareTo(object obj)
        {
            return i.CompareTo((obj as MyClass02).i);
        }
    }

    //对任意可比较类型数据进行升序排序
    class MyClass01
    {
        public T[] ArraySort<T>(T[] t) where T : IComparable
        {
            if (t.Length > 1)
            {
                for (int n = 0; n < t.Length; n++)
                {
                    for (int m = 0; m < t.Length - n - 1; m++)
                    {
                        //如果前者大于后者
                        if (t[m].CompareTo(t[m + 1]) >= 0)
                        {
                            T temp = t[m + 1];
                            t[m + 1] = t[m];
                            t[m] = temp;
                        }
                    }
                }
            }
            return t;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {         
            MyClass02[] c1 = new MyClass02[3];
            c1[0] = new MyClass02();
            c1[0].i = 11110;
            c1[1] = new MyClass02();
            c1[1].i = 230;
            c1[2] = new MyClass02();
            c1[2].i = 10;

            MyClass01 c3 = new MyClass01();
            c1 = c3.ArraySort<MyClass02>(c1);
            Console.WriteLine(c1[0].i);
            Console.WriteLine(c1[1].i);
            Console.WriteLine(c1[2].i);
        }
    }
泛型约束

1.引用类型约束

where T:class 引用类型用class表示约束,约束必须为一个类,可以是接口interface

2.值类型约束

where T:struct int、char类型都是struct

3.构造函数类型约束

where T:new() 指定类型T必须有构造函数

4.转换类型约束

就是我们可以通过装箱或者强制类型转换成目标类型的 类型都可以用于类型参数传入。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面向对象设计原则:
  • C#中抽象类与接口
  • 面向对象的三大特性:封装,继承,多态
  • 接口
  • Struct 结构体
  • 泛型
  • 泛型约束
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档