C#面向对象三大特性

来源:互联网 发布:jre 7u9 windows xp32 编辑:程序博客网 时间:2024/06/11 11:42

昨天阶段考试之后觉得自己对面向对象特性的理解比较模糊就重新找一些资料复习整理。

一、封装
上课笔记:为了数据不能够在外部进行人为的修改,故在设计类的时候把字段写成私有的,对象就不能够直接用“.”运算符点出来进行修改。
封装的功能是防止数据遭到破坏,为了修改数据会:(1)把私有的字段写成属性,这样可以通过属性进行操作(2)另外类里面会把方法写成公有的,然后再方法类里面对私有字段进行操作也可以修改数据
1、定义
把一个或多个项目封闭在一个物理的或逻辑的包中。封装只公开代码单元的对外接口,而隐藏其具体实现,尽量不对外公开代码。使用封装有很多好处,从设计角度来讲,封装可以对外屏蔽一些重要的信息,比如使用电脑的人只要知道怎么使用电脑就可以,不用知道这些功能具体是怎么实现的;从安全性考虑,封装使对代码的修改更加安全和容易,封装明确的指出了哪些属性和方法是外部可以访问的,这样当需要调整这个类的代码时,只要保证公有属性不变,公有方法的参数和返回值类型不变,那么就可以尽情的修改这个类,而不会影响到程序的其他部分;封装还避免了命名冲突的问题,封装有隔离作用,不同的类中可以有相同名称的方法和属性,但不会混淆,也可以减少耦合。

class Enemy{    //把字段写成私有的    private int hp;    //写出字段的属性    public int Hp    {        get{return hp;}        set{hp = value;}    }    //使用构造方法给字段赋初始值    //如果类里面只能有一个带参数的构造方法,此时创建对象时就只能调用带参数的构造方法,系统不会自动创建一个无参的构造方法    public Enemy(int hp)    {        this.hp = hp;    }    //方法位公有的,通过方法对字段进行操作    public void BeAttacked()    {        this.hp -=20;    }} class Program {        static void Main(string[] args)        {            Enemy enemy = new Enemy (100, 30);            enemy.Hp = 200;            enemy.BeAttacked();            Console.WriteLine (enemy.Hp);        }}

二、继承

**上课笔记**:如果不同的类里面有相同的成员,可以把相同的部分抽离出来放到一个公有的类里面,其他的类来继承这个公有的类,所有继承的类都可以使用这个公有的类里面的成员。定义一个公有类,公有的成员放到该类里面,其他类里面把公有的部分删除。base 关键字用于从派生类中访问基类的成员:  ● 调用基类上已被其他方法重写的方法。  ● 指定创建派生类实例时应调用的基类构造函数。基类访问只能在构造函数、实例方法或实例属性访问器中进行。

C# 中创建派生类的语法如下:

class
{

}
class :
{

}
多重继承就是一个子类可以继承多个父类,如下列:
class
{

}
class
{

}
class : , { … }
这个例子的基类,就是上面描述概念的时候提到的形状,形状是基类,而这个基类是个抽象的概念,而不是具体的,因此是抽象类,此类包含属性形状名称、输出形状周长和面积的方法以及计算形状周长和面积的抽象方法:

    /// <summary>    /// 形状基类        /// </summary>    public abstract class Shape    {        /// <summary>        /// 形状名称        /// </summary>        public string ShapeNameP { get; private set; }        public Shape(string shapeName)        {            ShapeNameP = shapeName;        }        /// <summary>        /// 输出形状周长        /// </summary>        /// <param name="permeter"></param>        public virtual void PrintPerimeter(double permeter)        {            Console.WriteLine(ShapeNameP + "Perimeter:"+ permeter);        }        /// <summary>        /// 输出形状面积        /// </summary>        /// <param name="area"></param>        public virtual void PrintArea(double area)        {            Console.WriteLine(ShapeNameP + "Area:" + area);        }        /// <summary>        /// 计算形状周长        /// </summary>        /// <returns></returns>        public abstract double CalculatePerimeter();        /// <summary>        /// 计算形状面积        /// </summary>        /// <returns></returns>        public abstract double CalculateArea();    }

下面再来看具体的子类,子类是圆,包含属性半径、计算周长和面积的方法:

    public class Circle : Shape    {        public double R { get; set; }        public Circle():base("Circle")        {            R = 0;        }        /// <summary>        /// 圆的周长        /// </summary>        /// <returns></returns>        public override double CalculatePerimeter()        {            return 2*Math.PI*R;        }        /// <summary>        /// 圆的面积        /// </summary>        /// <returns></returns>        public override double CalculateArea()        {            return Math.PI*R*R;        }    }

再来看看长方形,包含属性高度和宽度、计算周长和面积的方法:

    public class Rectangle : Shape    {        /// <summary>        /// 长方形的长度        /// </summary>        public double Width { get; set; }        /// <summary>        /// 长方形的高度        /// </summary>        public double Height { get; set; }        public Rectangle()          : base("Rectangle")        {            Width = 0;            Height = 0;        }        /// <summary>        /// 长方形的周长        /// </summary>        /// <returns></returns>        public override double CalculatePerimeter()        {            return (Width + Height) * 2;        }        /// <summary>        /// 长方形的面积        /// </summary>        /// <returns></returns>        public override double CalculateArea()        {            return Width * Height;        }    }

以下是调用的代码:

            Circle circle = new Circle();            circle.R = 20;           Rectangle rectangle = new Rectangle();            rectangle.Height = 30;            rectangle.Width = 20;            List<Shape> shapeList = new List<Shape>();            shapeList.Add(circle);            shapeList.Add(rectangle);            foreach (Shape shape in shapeList)            {                shape.PrintPerimeter(shape.CalculatePerimeter());                shape.PrintArea(shape.CalculateArea());            }

三、多态

这个多态对我目前而言理解还是比较抽象
废话不说先上网上找到的一些资料:
多态是指程序中同名的不同方法共存的情况,主要通过子类对父类方法的覆盖来实现多态。这样,不同类的对象可以用同名的方法完成特定的功能,但具体的实现方法却可以不同。比如说形状包含正方形、长方形、圆等,每个形状都有面积和周长,但是不同的形状计算面积和周长的方法都不同。

下面举例来说明多态
啥也不说先上代码

 enum MenPaiName    {        华山派,        少林派,        青城派,        崆峒派,        武当派,        丐帮,        峨眉派,        昆仑派,        点苍派,        雪山派    }    class KongFu    {        public MenPaiName name { get; set; }        public float power { get; set; }        public virtual void Attacked()        {            Console.WriteLine("门派攻击-10");        }    }    class  WuDang:KongFu    {        public WuDang(MenPaiName name,float power)        {            this.name = name;            this.power = power;        }        public float HP { get; set; }        public void LianGong()        {            Console.WriteLine("练功");        }    }    class ShaoLin : KongFu    {        public ShaoLin(MenPaiName name, float power)        {            this.name = name;            this.power = power;        }    }    class EMei:KongFu    {        public EMei(MenPaiName name, float power)        {            this.name = name;            this.power = power;        }        public override void Attacked()        {            Console.WriteLine("峨眉派攻击-20");        }    }    class  Race    {        public void YaoQing(KongFu kf)        {        }    }
            WuDang wuDang = new WuDang(MenPaiName.武当派, 30);            ShaoLin shaoLin = new ShaoLin(MenPaiName.少林派, 80);            EMei eMei = new EMei(MenPaiName.峨眉派, 99);            wuDang.Attacked();            shaoLin.Attacked();            eMei.Attacked();            //里氏转换原则            //1、只要是父类所在的地方都可以用子类来赋值,即可以把子类的对象赋值给父类的对象           //这样方法的参数如果作为父类的类型时,所有的子类都可以传进来,使得我们的方法得到啦进一步的重用           //但是对象在调用成员时,只能调用父类里面的成员,而子类里面的成员会被屏蔽掉            KongFu kongFu = new WuDang(MenPaiName.武当派, 60);            //2、父类可以强制转换成子类。            WuDang w = (WuDang) kongFu;            //使用as类型转换符在不同的引用类型之间进行类型转换,如果转换成功对象就是转换后的类型,如果转换不成功对象时空            KongFu kong = new EMei(MenPaiName.峨眉派, 50);            WuDang e = kong as WuDang;            if (e == null)            {                Console.WriteLine("e为空");            }             int a = 10;            //把一个子类型赋值给了一个引用类型,此操作称为装箱操作            object obj = a;            //把引用类型转换为值类型的操作称为拆箱操作            int b = (int) obj;            Console.WriteLine(b+1);            /*当我们把子类的对象赋值给父类以后,父类的对象里面存的是子类的对象,调方法时仍然调的是父类里面的方法,这也意味着任何一个子类的对象赋值给父类以后每一个子类调用的方法都一样,每一个子类的行为就体现不出来啦,此时可以把父类里面的方法写成虚方法,然后在子类里面进行重写,这样在调方法后就会调子类重写后的方法,如果子类不重写,就调父类的方法*/            kong.Attacked();        }    }