zoukankan      html  css  js  c++  java
  • C#面向对象高级语法(一)

    密封(sealed)类和方法

    sealed关键字可以用来修饰类、变量和方法。sealed修饰符放在类之前,就将类声明为密封类,表示该类不能被继承。密封类主要防治意外的派生,同时可以提高程序的运行性能。在非密封类中,如果要防止一个实例成员在子类中被重写,就可以将该成员声明为密封成员,包括密封方法、密封属性、密封索引器等。对于密封方法,它只能用于对基类的虚方法进行重写,并提供具体的实现。所以在密封方法的声名中,sealed修饰符总是和override修饰符同时使用,以防止派生类进一步重写该方法。

    比如:

     1 using System;
     2 class A
     3 {
     4     public virtual void F()
     5     {
     6         Console.WriteLine("A.F");
     7     }
     8 
     9     public virtual void G()
    10     {
    11         Console.WriteLine("A.G");
    12     }
    13 }
    14 
    15 class B : A
    16 {
    17     sealed override public void F()
    18     {
    19         Console.WriteLine("B.F");
    20     }
    21 
    22     override public void G()
    23     {
    24         Console.WriteLine("B.G");
    25     }
    26 }
    27 
    28 class C : B
    29 {
    30     override public void G()
    31     {
    32         Console.WriteLine("C.G");
    33     }
    34 }

    类B对于基类A中的两个虚方法均进行了重载,其中,F方法使用了sealed修饰符,成为了一个密封方法。G方法不是密封方法,所以在B类的派生类C中,可以重载G方法,但是不能重载F方法。

    1. 访问控制(Access Control)

    关键字

    说明

    public

    所有类均可访问

    private

    只能被它所在的类内部访问

    protected

    可以被类内和所有子类访问

    internal

    限定在类所在的程序内

    1. 抽象类与抽象方法

      在现实生活中我们发现,一个类的某个或某几个方法是无法具体实现的。例如图形Shape类中的画图draw()方法,当你不知道具体要画什么形状,比如长方形或者三角形时,怎么可能实现一个画形状的方法呢?在C#中,这样的方法叫做抽象方法,一个类如果有一个或多个抽象方法,这个类就叫做抽象类。

      用abstract关键字来修饰一个类时,该类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。

    • 抽象类必须被继承,抽象方法必须被重写。
    • 抽象类不能被直接实例化,因此它一般用作其他类的基类。
    • 抽象方法只须声明,而无须实现。定义了抽象方法的类必定是抽象类。

    实例:两个类Circle和Rectangle,计算面积:

    class Circle
    {
    public float r;
    Circle(float r)
    {
    this.r = r; // this指"这个对象"
    }
    public float Area()
    {
    return (float)3.14 * r * r;
    }
    } 
    
    class Rectangle
    {
    public float width, height;
    Rectangle(float w,float h)
    {
    this.width = w;
    this.height = h;
    }
    public float Area()
    {
    return width * height;
    }
    }
    

      

    假设有若干个Circle以及若干个Rectangle,希望计算它们的面积,直截了当的做法是将他们分别放在2个数组中,用两个循环,加上一个加法,但这种方法不是最好的。因为如果还有其他形状,日triangle、ellipse等,上述方法显得"累赘"。希望有一种统一的表示,例如用给一个数组Shape[],接收所有的形状,然后用

    1 foreach(Shape shape in sps)
    2 {
    3     area_total = shape.Area();
    4 }

    完成调用。这样的话,我们仅需要一个抽象类Shape。

    实例如下:

    abstract class Shape
    {
        public abstract float Area();
    }
    
    
    class Circle : Shape
    {
        public float r;
        public Circle(float r)
        {
            this.r = r;
        }
        public override float Area()
        {
            return (float)3.14 * r * r;
        }
    }
    
    
    class Rectangle : Shape
    {
        public float width, height;
        public Rectangle(float width, float height)
        {
            this.width = width;
            this.height = height;
        }
    
        public override float Area()
        {
            return width * height;
        }
    }
    
    
    public class AbstractShapeTest
    {
        static void Main(string[] args)
        {
    
            Shape circle1 = new Circle((float)2.0);
            Shape rectangle1 = new Rectangle((float)3.4, (float)6.8);
            Console.WriteLine("Circle's Area is:", circle1.Area());
            Console.WriteLine("Rectangle's Area is:", rectangle1.Area());
    
            Console.ReadKey();
        }
    }
    
    // output:
    // Circle's Area is:12.56
    // Rectangle's Area is:23.12

    接口(interface)

    从本质上讲,接口是一种特殊的抽象类,这种抽象类中指定实现该接口的类必须提供的成员,实现接口的类提供接口成员的实现。那么为什么要使用接口?

    • 通过接口可以实现不相关类的相同行为,而无须考虑这些类之间的层次关系。
    • 通过接口可以指明多个类需要实现的方法。
    • 通过接口可以了解对象的交互界面,而无须了解对象对应的类。

    另外,从软件设计的角度来看,我们希望把复杂的应用系统分割为多个模块,每个模块完成独立的功能,模块之间能够协同工作,这样的模块称为组件。组件可以单独开发、编译和测试,把所有的功能结合到一起,就得到了完整的系统。要使组件能够协同工作,就必须在组件之间提供一种工作协议,而接口就非常适合作为组件之间的协议描述工具。

    1. 接口的定义

      接口定义格式如下:

      [接口修饰符] interface 接口名 [:基接口列表]

      {

          // 接口成员

      }

      其中,接口修饰符是可选的,只允许为new修饰符或者访问修饰符public、protected、internal或protected。基接口也是可选的,接口可以从零个或多个接口继承。interface和接口名是必需的,接口名是一种标示符,应符合标示符的命名规则,最好能体现接口的含义和用途。根据命名惯例,接口名总是以大写字母I开头。

      接口成员具有如下要求:

    • 接口成员必须是方法、属性、事件或索引器。接口不能包含常量、字段、运算符和实例构造函数、析构函数或类型,也不能包含类的静态成员。
    • 接口只包含方法、属性、事件或索引器的签名,而不提供他们的实现。
    • 接口成员都是public类型的,但是不能使用public修饰。

    下面是接口的一个实例:

    1 interface ITest
    2 {
    3     string Name
    4     {
    5         get;
    6         set;
    7     }
    8     void MyMethod();
    9 }

    接口可实现多重继承,即一个接口可以继承多个接口,在冒号后跟上一个由逗号分开的基接口列表,例如:

     1 interface ITest1
     2 {
     3     void M1();
     4 }
     5 
     6 interface ITest2
     7 {
     8     void M2();
     9 }
    10 
    11 interface ITest3
    12 {
    13     void M3();
    14 }
    15 
    16 interface ISubTest : ITest1, ITest2, ITest3
    17 {
    18     //
    19 }

    ISubTest将多重继承ITest1、ITest2和ITest3,将同时具备方法M1、M2和M3。

    1. 接口的实现

      在类中继承接口叫做对接口的实现(Implementation),例如:

     1 interface Collection
     2 {
     3     //方法是共有的public,C#编译器会自动加上public关键字
     4     void Add(Object obj);
     5     void Delete(Object obj);
     6     Object Find(Object obj);
     7     int CurrentCount();
     8 }
     9 
    10 
    11 
    12 class Queue : Collection
    13 {
    14     public void Add()
    15     {
    16         // ...
    17     }
    18 
    19     public void Delete()
    20     {
    21         // ...
    22     }
    23 
    24     public Object Find(Object obj)
    25     {
    26         // ...
    27     }
    28 
    29     public int CurrentCount()
    30     {
    31         // ...
    32     }
    33 }

    再看一个完整的示例,为了演示把之前使用的Shape抽象类变为接口:

     1 interface IShape
     2 {
     3     void Draw();// 不能有任何实现的部分
     4     //{
     5     // System.Console.WriteLine("draw in shape");
     6     //}
     7 }
     8 
     9 class Circle : IShape
    10 {
    11     private double r;
    12     public Circle(double r)
    13     {
    14         this.r = r;
    15     }
    16 
    17     public void Draw()
    18     {
    19         Console.WriteLine("draw in circle,r={0}", r);
    20     }
    21 }
    22 
    23 class Rectangle : IShape
    24 {
    25     private double width;
    26     private double height;
    27 
    28     public Rectangle(double width, double height)
    29     {
    30         this.width = width;
    31         this.height = height;
    32     }
    33 
    34     public void Draw()
    35     {
    36         Console.WriteLine("draw in rectangle,width={0},heigth={1}", width, height);
    37     }
    38 }
  • 相关阅读:
    [Asp.net 开发系列之SignalR篇]专题四:使用SignalR实现发送图片
    [Asp.net 开发系列之SignalR篇]专题三:使用SignalR实现聊天室的功能
    [Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能
    [Asp.net 开发系列之SignalR篇]专题一:Asp.net SignalR快速入门
    [后端人员耍前端系列]Bootstrap篇:30分钟快速掌握Bootstrap
    工欲善其事,必先利其器
    ASP.NET 开发必备知识点(2):那些年追过的ASP.NET权限管理
    ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上
    [你必须知道的NOSQL系列]专题二:Redis快速入门
    [你必须知道的NOSQL系列]专题一:MongoDB快速入门
  • 原文地址:https://www.cnblogs.com/fanyong/p/2754284.html
Copyright © 2011-2022 走看看