安静且高效一点就好3

今天是第三天啦


前言

静态与非静态的各个要点,还有就是对继承中的知识进行补足,里氏转换原则的了解,is as运算符的基本常规使用,实现多态的三种方式,虚方法,抽象类,接口


提示:以下是本篇文章正文内容,下面案例可供参考

一、静态与非静态

1.静态的定义:无论什么成员被static修饰,那么这个成员变为静态成员,列如类被修饰则为静态类,方法被修饰则为静态方法,字段则变为静态字段等等…下面将详细对静态与非静态进行分析:
1.如果当前成员是静态成员,那么需要加上static关键字进行修饰。
2.两者之间的调用的区别:
—>静态成员在调用的时候需要使用类名来调用。---->属于类
—>但是非静态成员在调用的时候要求使用对象名来调用。---->对象
3.静态类:静态类中只允许出现静态成员,语法要求
4.非静态类:
—>在非静态类中允许出现静态成员,也允许出现非静态成员。
—>在非静态函数中即允许访问非静态成员,也允许访问静态成员(如果你要访问其他类的静态成员, 前提是你要访问的成员必须被public出来)
5.什么时候用非静态?
----->静态成员只有在整个程序结束的时候才能够被释放资源。所以说,我们的程序中静态成员应该是越少越好。
6.静态构造函数不能加访问修饰符,静态构造函数会比实例构造函数先执行
代码如下(示例):

namespace 静态static
{
    class Program
    {
        public static int age = 10;
        static void Main(string[] args)
        {
            // Program pg = new Program();
            Student student = new Student();
            student.Name = "张三";
            student.Age = 10;
            student.SchoolName = "人大附中";



            student.StudentSayHello();

            ----->静态字段/属性只能通过 :类名.成员名  来访问
           ----->静态成员 在类中只有一份 ,为类中多有对象所共有
            // Student.zz;


            ----->静态类不能被实例化
            // Persion p = new Persion();
            ----->静态方法也要通过类名来调用
            Persion.PersionSayHello();

            Console.ReadKey();
           
        }       
    }

    class Student
    {
       ----->静态字段
       public static int zz;

        ----->实例构造函数
        public Student()
        {

        }
        ----->静态构造函数不能加访问修饰符,静态构造函数会比实例构造函数先执行
        static Student()
        {

        }
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private int age;
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        private string schoolName;
        public string SchoolName
        {
            get { return schoolName; }
            set { schoolName = value; }
        }
        public void StudentSayHello()
        {
            
            Console.WriteLine("我叫{0},年龄{1},学校名称{2}",this.name,this.age,this.schoolName);
        }
    }
    ----->静态类中只能包含静态成员,不能包含实例成员
     class Persion
    {
        private static int age;
        public static int Age
        {
            get { return age; }
            set { age = value; }
        }
        private static string name;
        public static string Name
        {
            get { return name; }
            set { name = value; }
        }
        public static void PersionSayHello()
        {
            Console.WriteLine("我是人类{0}",name);
            
        }
    }
}

二、继承

1.里氏转换原则以及is as运算符的基本使用

【@】里氏替换原则:
1.子类可以赋值给父类
2.如果父类中装的是子类对象,那么可以将这个父类转换为"对应"的子类对象
【@】我们可以使用is.as运算符帮助我们进行转换:
1.is、as都表示类型转换,不同的是,他们的返回值不一样。
2.is:是否可以执行类型转换 ,返回值是bool类型。
3.as:表示类型转换,如果成功,则返回对应的对象,如果失败则返回null。
注:对知识点进行补充—>//null “” string s=null string s="“这两个一个” "是在内存中开辟了控件,null一个是没有开辟内存空间

代码如下(示例):

namespace 里氏转换原则
{
    class Program
    {
        static void Main(string[] args)
        {
            //开放封闭原则:对程序的扩展开放,对代码的修改保持封闭,了解即可

            //子类可以赋值给父类类型的变量(前提是,这些都是在继承的基础上)
            
            Student student = new Student();
            Persion persion = student;//隐士转换

            //Persion p = new Student();//也可以直接new

            //---->如果父类中装的是子类对象,那么可以将这个父类转换为"对应"的子类对象
           // Student s = (Student)p;
            Console.WriteLine("转换成功");




            //使用is 和 as关键字进行一个转换
            Persion p = GetSingle(2);

            #region 使用is执行转为
            if (p != null)
            {
                if (p is Student)//表示p对象能够转换成Student
                {
                    //如果返回值为true,则可以直接开始转换
                    Student stu = (Student)p;
                    stu.StudentSayHello();
                }
                else if(p is Teacher)
                {
                    Teacher t = (Teacher)p;
                    t.TeacherSayHello();
                }
            }
            else
            {
                Console.WriteLine("当前p为空");
            }
            #endregion
#region as转换

            Teacher teach= p as Teacher;
            if (teach != null)
            {
                teach.TeacherSayHello();
            }
            else
            {
                Console.WriteLine("当前t为null");
            }
#endregion
            Console.ReadKey();
        }



        static Persion GetSingle(int number)
        {
            Persion per = null;
            switch (number)
            {
                case 1:
                    per = new Student();
                    break;
                case 2:
                    per = new Teacher();
                    break;
                default:
                    //如果传入的值与每一个case都不匹配,那么就直接执行default中的语句
                    break;
            }
            return per;
        }
    }
    class Persion
    {

    }
    class Student:Persion
    {
        public void StudentSayHello()
        {
            Console.WriteLine("我是学生,SayHello");
        }
    }
    class Teacher : Persion
    {
        public void TeacherSayHello()
        {
            Console.WriteLine("我是老师");
        }

    }
}

二、多态

虽然多态是一个很抽象的问题,但是我对多态的理解如下:
1.多态意在让一个对象能够表现出多种的类型、状态。
2.多态:就是用父类类型变量,后面跟着子类的实例,然后可以调用子类的函数(这个就叫表现出多种类型,状态)。
3.实现多态的有三种方法:虚方法,抽象类,接口。

1.虚方法

虚方法的实现:
–>在父类的函数前面加个virtual关键字
—>在子类每个函数前面加上override关键字
代码如下(示例):

namespace 多态
{
    class Program
    {
        static void Main(string[] args)
        {
            ----->多态
            ----->封装、继承
            ----->多态意在让一个对象能够表现出多种的类型、状态

           ----->多态:就是用父类类型变量,后面跟着子类的实例,然后可以调用子类的函数(这个就叫表现出多种类型,状态)----->多态的好处:我们把不同的子类对象都当做父类来看,从而屏蔽子类之间的差异
            ----->写出通用的代码,做出通用的编程,以适应需求的不断改变。


            ----->实现多态的有三种方法:虚方法,抽象类,接口
            ----->虚方法的实现:
                 -->在父类的函数前面加个virtual关键字
                 --->在子类每个函数前面加上override关键字

            Chinese c1 = new Chinese("张三");
            Chinese c2 = new Chinese("李四");
            Japanese j1 = new Japanese("松下电器");
            Japanese j2 = new Japanese("渡边");
            Korea k1 = new Korea("金秀贤");
            Korea k2 = new Korea("全智贤");
            American a1 = new American("科比布莱恩");
            American a2=new American("奥巴马");


            ----->父类只能调用自己的成员,意思就是说父类类型的变量,存储的是子类的实例,但是也只能调用父类的成员,不能调用子类类型的成员
            ---->数组虽然是父类类型的,但是全部都是子类类型的对象
            Persion[] pers = { c1,c2,j1,j2,k1,k2,a1,a2};
            for (int i = 0; i < pers.Length; i++)
            {
                pers[i].SayHello();----->这里打出来的全是父类方法的值,父类只能调用自己的成员
                                   ----->如果能让父类表现出子类类型出来,就可以。(多态)



                #region Old Method------这里是老方法
                //if (pers[i] is Chinese)
                //{
                //    ((Chinese)pers[i]).SayHello();
                //}
                //else if (pers[i] is Japanese)
                //{
                //    ((Japanese)pers[i]).SayHello();
                //}
                //else if (pers[i] is Korea)
                //{
                //    ((Korea)pers[i]).SayHello();
                //}
                //else if (pers[i] is American)
                //{
                //    ((American)pers[i]).SayHello();
                //}
                #endregion
            }

            Console.ReadKey();
        }
    }
    class Persion
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public Persion(string name)
        {
            this.Name = name;
        }
        ----->标记这个函数是虚函数,可以被子类重写。
        public virtual void SayHello()
        {
            Console.WriteLine("我是人类");
        }
    }
    class Chinese:Persion
    {
        public Chinese(string name) : base(name)----->父类重写了构造函数,把无参的构造函数干掉了,所以要显式的调用父类有参的构造函数
        {

        }
        public override void SayHello()
        {
            Console.WriteLine("我叫{0},我是中国人",this.Name);
        }
    }
    class Japanese : Persion
    {
        public Japanese(string name) : base(name)
        {

        }
       ----->override表示重写父类的虚函数
        public override void SayHello()
        {
            Console.WriteLine("我叫{0},我是日本人",this.Name);
        }
    }
    class Korea:Persion
    {
        public Korea(string name):base(name)
        {

        }
        public override void SayHello()
        {
            Console.WriteLine("我叫{0},我是韩国人",this.Name);
        }
    }
    class American : Persion
    {
        public American(string name):base(name)
        {

        }
        public override void SayHello()
        {
            Console.WriteLine("我叫{0},我是美国人",this.Name);
        }
    }
}

2.抽象类

1.抽象类需要abstract关键字来修饰
2.里面可以包含抽象成员,也可以包含普通成员,代码中有详细的概括
代码如下(示例):

namespace 抽象类
{
    class Program
    {
        static void Main(string[] args)
        {
            Animal a = new Dog();

            Dog d = new Dog();

            -->如果父类中的函数你知道怎么写(方法内有具体的实现),用虚方法实现多态
            -->反之,使用抽象类来实现多态(方法内没有具体实现)

            -->抽象类特点:
            -->1、子类如果继承了一个抽象的父类,那么这个子类必须将抽象父类中的所有成员重写。(除非这个子类也是抽象类)
            -->2、抽象类中除了有抽象成员外,还可以有普通的成员,继承那一套抽象类同样可以使用
            -->3、子类重写的父类抽象的函数,必须跟父类的抽象函数具有相同的方法签名(相同的参数和相同的返回值)
        }
    }
   abstract class Animal
    {
     	-->当前这个函数 是抽象函数
       -->当父类不知道子类如何实现的时候,可以将父类提供的函数标记为抽象函数
        -->抽象函数,必须存在于抽象类中
        public abstract string Bark();


        #region 抽象类中的非抽象成员
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private int age;
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        private char gender;
        public char Gender
        {
            get { return gender; }
            set { gender = value; }
        }
        public void SayHello()
        {
            Console.WriteLine("我是抽象类");
        }
        #endregion
    }
    class Cat : Animal
    {     

       -->重写抽象类中的抽象方法子类仍然需要用override关键字
        public override string Bark()
        {
            Console.WriteLine("猫咪喵喵叫");
            return "123";
        }
    }
    class Dog : Animal
    {
        public override string Bark()
        {
            Console.WriteLine("狗狗汪汪叫");
            return "123";
        }
    }
}

3.接口

1.接口概念:接口侧重于表示 1、能力 2、规范
2.接口的名字一般都以"I"开头,侧重于表示一种能力
3.接口可以多继承
4.接口中的成员不写访问修饰符,默认是public,而类中的成员不写访问修饰符,默认是private
5.接口的名字一般都以"I"开头,侧重于表示一种能力
6.接口实现多态和抽象类实现多态是一样的,都是声明父类去指向子类对象…
代码如下(示例):

namespace 接口
{
    class Program
    {
        static void Main(string[] args)
        {
            --->接口概念:接口就表示 1、能力 2、规范
            --->实现多态
            --->接口实现多态和抽象类实现多态是一样的,都是声明父类去指向子类对象

            IKouLan i = new Student();
            i.KouLan();

            IFly i2 = new Student();
            i2.Fly();

            Console.ReadKey();
            


           --->在什么情况下用虚方法,抽象类,接口
            --->基类有具体实现用虚方法。
           ---->基类没有具体实现,用抽象类,如果有子类不需要实现的,偏向于侧重于一种规范的就使用接口。

        }
    }
    --->为了满足Student的多继承,我们使用接口
    --->接口的名字一般都以"I"开头,侧重于表示一种能力
    --->接口可以多继承
    interface IKouLan
    {
        --->类中的成员不写访问修饰符,默认是private
        --->而接口中的成员不写访问修饰符,默认是public
        --->不允许添加访问修饰符
        void KouLan();
    }
    interface IFly
    {
        void Fly();
    }
    class Persion
    {
        public void CHLSS()
        {
            Console.WriteLine("我是人类");
        }
       --->不能再父类中封装扣篮的函数,因为并不是所有的子类都会扣篮
        //public void KouLan()
        //{
        //    Console.WriteLine("NBA球员能够扣篮");
        //}
    }
    class Student : Persion, IKouLan, IFly
    {
        public void Fly()
        {
            Console.WriteLine("学生可以飞");
        }

        public void KouLan()
        {
            Console.WriteLine("学生会扣篮");
        }
    }
    class Teacher : Persion, IKouLan
    {
        public void KouLan()
        {
            Console.WriteLine("老师也会扣篮");
        }
    }
    class NoLegs : Persion
    { }
    class NBAPlay : IKouLan
    {
        public void KouLan()
        {
            Console.WriteLine("NBA球员会扣篮");
        }
    }
}

3.接口的特点

1.接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。
2.类中的成员默认的访问修饰符是private ,而接口中默认的访问修饰符是public
3.接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。
4.接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。
5.接口与接口之间可以继承
6.接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)
7.实现接口的子类必须实现该接口的全部成员。
8.一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。

注:当一个抽象类实现接口的时候,需要子类去实现接口。


总结

多写写多看看得到的总会多一点。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值