应无所住,而生其心
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

面向对象中的继承, 虚方法, 抽象类,抽象函数,接口等概念

6691人阅读 2020/9/28 11:37 总访问:4844684 评论:2 收藏:2 手机
分类: 软件架构


面向对象继承中的构造函数问题:

在继承的前提下,会先执行父类的构造函数,默认执行无参构造函数。

因为在子类中是需要一个父类的对象,这样才可以继承到父类的属性方法等,在子类中可以使用base访问父类的内容

       

如果父类没有无参的构造函数,可以手动执行父类的构造函数。语法base(参数列表)执行父类的构造函数


先创建父类的对象在创建子类的对象
先创建父类 , 因为子类需要继承父类的内容,有base执行父类所以先创建父类

析构函数是先执行父类的还是子类的
先销毁子类,因为子类中有base指向父类的地址,所以在销毁子类的时候相当继承链的父类也会被gc销毁,因为gc销毁的原理是没有引用的时候才会被销毁,所以先销毁子类,因为子类销毁了,父类就没有引用了,父类就会被gc销毁。



      
         


虚方法:     

作用:用与被子类重写,使用多态,实现多态的一种手段        

关键字: virtual 

重写父类虚方法关键字:override,可以被重写也可以不被重写




使用虚函数实现上边不同等级员工发工资的例子:
公司有不同的人,员工有不能的等级,普通员工工资是3000,p2工资是5000,p3工资8000,如何使用面向对象的思想去实现

父类:

    public class People
    {
        public int Age { get; set; }
        public string Name { get; set; }

        //发工资的虚方法
        public virtual void Salary()
        {
            Console.WriteLine("发工资3000");
        }

    }

三个子类:   

    //普通员工
    public class Normal : People
    {
        /// <summary>
        /// 重写父类的方法
        /// </summary>
        //public override void Salary()
        //{
        //    Console.WriteLine("发工资3000");
        //}
    }
    //中级员工
    class P2:People
    {
        /// <summary>
        /// 重写父类的方法
        /// </summary>
        public override void Salary()
        {
            Console.WriteLine("发工资5000");
        }
    }
    //高级员工
    class P3 : People
    {
        /// <summary>
        /// 重写父类的方法
        /// </summary>
        public override void Salary()
        {
            Console.WriteLine("发工资8000");
        }
    }

使用: 

static void Main(string[] args)
        {
            People people = new Normal();
            people.Salary();

            People people2 = new P2();
            people2.Salary();

            people = new P3();
            people.Salary();

            Console.ReadLine();
        }

 效果如下:
 

       

有虚方法,有没有虚属性,或者有没有虚索引?

有虚属性,因为属性本身其实是两个方法,也有虚索引,因为索引是一种特殊的属性,本质也是方法



抽象类与抽象函数


抽象类的作用:为了被子类继承,从而实现多态。是一种约定,约定必须要具体那些方法。

抽象函数作用:都是为了被子类重写,重写实现多态(同一个对象同一个方法,指向不同从而实现多态)

抽象函数特点:不能有方法体,子类必须重写        

关键字:abstract


虚函数和抽象函数的异同点:

相同点: 都可以被子类重写从而实现多态

不同点: 

1:虚函数有方法体,抽象函数没有方法体。也就是说虚函数可以有默认实现,抽象函数不行 

2:虚函数可以被重写,也可以不被重写,抽象函数必须被重写

3:抽象方法只能在抽象类中,抽象方法不能在普通类中
   

抽象类和普通类的异同点:

相同点:都可以被继承,也可以继承其他类,都可以有普通方法

不同点:

1:普通类可以被实例化,抽象类不行,抽象类提供一种约定一种类的模板,不能被实例化,因为实例化是没有意义,具体的类有实现才有意义

2:抽象类才能有抽象方法,普通类不行

使用抽象类实现不同图形的面积计算
父类:      

    /// <summary>
    /// 抽象类
    /// </summary>
    public abstract class Shape
    {
        public abstract int length { get; set; }

        public string type { get; set; }

        /// <summary>
        /// 抽象方法
        /// </summary>
        public abstract void Area(int r);
    }

         两个子类:   

    public class Circle : Shape
    {
        public const double pi = 3.14;

        /// <summary>
        /// 重写方法,实现方法
        /// </summary>
        public override void Area(int r)
        {
            Console.WriteLine("圆形面积:"+(pi * r * r));
        }

        public override int length
        {
            get
            {
                return length;
            }
            set
            {
                length = value;
            }
        }
    }
    
        public class Rectangle : Shape
    {
        public override void Area(int r)
        {
            Console.WriteLine("矩形面积:"+(r * r));
        }

        public override int length
        {
            get
            {
                return length;
            }
            set
            {
                length = value;
            }
        }
    }

使用:   

    class Program
    {
        static void Main(string[] args)
        {

            Shape shape = new Circle();
            shape.Area(6);

            shape = new Rectangle();
            shape.Area(6);    

            Console.ReadLine();
        }
    }

效果如下:



有没有抽象属性?
可以有抽象属性,用法和虚属性类似,不同点:虚属性可以有自己的实现,抽象属性不行        


接口(在低版本中不能有方法体,在高版本中接口也可以有方法体,我们这里讨论低版本中)

和抽象类非常类似:都是一种约定,约定必须要具备的功能,接口里边的方法都是抽象的,不能有方法体。接口里边的方法默认都是公共的,默认都是抽象的,所以定义的时候只需要定义返回值方法名参数,public和abstract会自动加上                


接口和抽象类的异同点:

相同点:都是一种约定,约定必须要具备的功能

不同点:
1:接口里边不能有普通方法,但是抽象类可以 
2:重写接口的方法不需要加override,但是重写抽象函数必须要加
3:接口可以多重继承,但是抽象类不行

使用接口的方式来实现不同类型图形的面积计算   

    public interface IShape
    {
        void Area(int r);

        int length { get; }

        int this[int index] { get; }
    }
    
    //矩形类
     public class Renctangle : IShape
    {
        public void Area(int r)
        {
            Console.WriteLine("矩形面积" + r * r);
        }


        public int length
        {
            get
            {
                return length;
            }
        }


        public int this[int index]
        {
            get { return 1; }
        }
    }
    
    //圆形类
    public class Circle : IShape
    {
        public void Area(int r)
        {
            Console.WriteLine("圆形面积:" + 3.14 * r * r);
        }


        public int length
        {
            get
            {
                return length;
            }
        }


        public int this[int index]
        {
            get { return 1; }
        }
    }

效果和用法和上面一样

     




欢迎加群讨论技术,群:677373950(满了,可以加,但通过不了),2群:656732739

评价