C#面向对象程序设计

时间:2023-02-04 10:31:32

面向对象编程(Object Oriented Programming,OOP)。

面向对象的三大特性

 特性

 优势

 封装

 保证对象自身数据的完整性、安全性

 继承

 建立类之间的关系,实现代码复用,方便系统的扩展

 多态

 相同的方法调用可实现不同的实现方式

一、封装

封装是面向对象的重要内容,是面向对象的三大特性之一。它用于隐藏内部实现,对外只暴露对象的基本操作,而不会让其他对象影响类的内部实现。在类中,构建封装字段,我们可以创建属性,将属性和字段封装在一起。保证了对象自身数据的完整性、安全性。

封装为我们带来如下好处:

  • 避免使用非法数据赋值。
  • 保证数据的完整性。
  • 避免类内部发生修改时,导致整个程序的修改。

类的成员:字段、属性、方法

在C#中,我们通常不会直接访问类中的字段,而是通过get和set访问器来访问,这种实现方式我们称为属性。

如:

class  Student

{

      //字段

     private stirng name;

     private int age;

    

     //封装好的属性

     public string Name

     {

          get{ return name; }

          set{ name=value;}

     }

 

    public int Age

     {

          get{ return age; }

          set{

                    //属性是聪明的字段

                    if( value>0 && value<100 )

                    {

                         age=value;

                    } 

                    else

                    {

                         age=18;

                    }

               }

     }

 

     //方法

     访问修饰符  返回类型  方法名(参数)

     {

            //方法体

     }

}

二、继承 

在C#中,一个类可以继承另一个类。如Student和Teacher类都继承Person类:

public class Student : Person {   } 

public class Teacher : Person {   }

继承必须符合is a 的关系,被继承的类称为父类或基类,继承其他的类称为子类或派生类。

继承机制很好地解决了代码复用的问题,方便系统的扩展。

子类继承父类的成员,并且可以拥有自己特有的成员。

C#中,this关键字代表当前实例,通过它可以访问类本身的成员。base关键字代表父类,可以用于访问父类的成员。例如:在子类中,调用父类的属性、方法、构造方法。

继承具有传递性,如果class A : B ;class B : C,则A也可以访问C的成员。

C#中的继承具有单根性,一个类不能够同时继承自多个父类。

继承模拟了现实世界的关系,继承实现了代码的重用,继承使得程序结构清晰,子类和父类的层次结构清晰,最终的目的是使子类只关注子类的相关行为和状态,无须关注父类的行为与状态。

三、多态

多态是指两个或多个属于不同类的对象,对于同一个消息(方法调用)作出不同响应的行为方式。

使用抽象方法和虚方法都可以实现多态性。

使用抽象类和抽象方法实现多态

(1)抽象方法是一个没有实现的方法,通常在定义方法时增加关键字abstract 可以声明抽象方法。

访问修饰符 abstract  返回类型  方法();

(2)含有抽象方法的类必须是抽象类。但抽象类中可以有非抽象方法,且非抽象方法可以有方法体。同样,我们用abstract 关键字来定义一个抽象类。

访问修饰符 abstract  class 类名 {   }

常见错误:

1.对于抽象类有一个限制:它不能被实例化。

由于无法创建抽象类的实例对象,所以只能通过它的子类来实现该类的方法,除非它的子类也是一个抽象类。

2.抽象类不能是密封或者静态的:如果给抽象类增加密封类的访问修饰符sealed或者static,系统会提示错误,其实很容易理解,抽象类如果不被子类继承并实现它的抽象方法,便没有实际意义。

重写抽象方法:

抽象方法必须在其子类中实现,除非它的子类也是抽象类。在子类中的实现一个抽象方法的方式是使用override关键字来重写抽象方法。

访问修饰符 override  返回类型  方法(参数)

{  

     //方法体

}

使用虚方法实现多态 

C#中用virtual 关键字修饰的方法称为虚方法。虚方法必须有具体的实现,在父类中提供默认实现,也可以被子类重写。

使用虚方法实现多态:

在父类中定义虚方法,然后在子类中可以重写虚方法,也实现了面向对象的多态。

虚方法是用virtual 关键字修饰的。

访问修饰符  virtual  返回类型  方法(参数)

{

     //方法体

}

子类中重写父类的虚方法时,采用override关键字

访问修饰符 override  返回类型  方法(参数)

{  

     //方法体

}

总而言之,虚方法除了提供默认的实现之外,还可以重写自定义的实现方式,大大增加了程序的灵活性。

虚方法与抽象方法的区别

 虚方法

 抽象方法

 用virtual修饰  用abstract修饰
 必须有方法体,哪怕是一个分号  不允许有方法体
 可以被子类override重写  必须被子类override重写
 除了密封类外都可以写  只能在抽象类中

接口

接口:接口是某类行为或功能的抽象,是一种规范或者标准,或者说是一种契约。

C#中,一个类只能继承一个类,但能实现多个接口。

C#中,使用interface关键字来定义接口。

public interface IName {   }

 .NET中的接口的使用要注意以下几点:

(1)接口中可以包含属性、方法、索引器等(不包含字段),但是都不能够实现,接口中的方法和属性。

接口中的方法:

public interface ISampleInterface

{

      void ShowName();

}

接口中的属性:

public interface  ISampleInterface

{

      string Name

      {

             get;

             set;

      }

}

(2)定义一个接口的名称通常都是以“I”开头。

(3)我们习惯说法是实现了一个接口,继承了一个类。

(4)实现一个接口的语法与继承类似:class  Student : IComparable。

(5)如果类已继承了一个父类,则以“,”分隔父类和接口。

class  Student : Person,IComparable

接口的典型应用:

(1)接口作为参数的意义:

接口作为参数传递时,实际上要传递的就是实现这个接口的对象。

(2)接口作为返回值的意义:

接口作为返回值实际上就是返回一个实现接口的对象。

接口小结:

(1)接口是继承单根性的扩张。

(2)接口是一种规范和标准。

(3)接口屏蔽了实现的细节。

(4)接口的使用方便团队协作开发。