zoukankan      html  css  js  c++  java
  • 在派生类中引发基类事件

    1、  在创建基类时,若涉及到事件,事件是特殊类型的委托,只可以从声明它们的类中调用,派生类无法直接调用基类中声明的事件,但是在多数情况,会需要允许派生类调用基类事件,这时,可以再包含该事件的基类中创建一个受保护的虚调用方法,通过调用或重写此调用方法,派生类便可以间接调用该事件。

    注:不要在基类中声明虚拟事件,也不要在派生类中重写这些事件,C#编译器无法正确处理这些事件,并且无法预知该派生的事件的用户是否真正订阅了基类事件。

    和下面的程序示例都来自:https://msdn.microsoft.com/zh-cn/library/hy3sefw3.aspx

    2、  插入知识点:virtual和abstract的区别:

    virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义(子类方法前都必须添加override),因此虚拟方法和抽象方法都不能是私有的;

    virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现;

     virtual可以被子类重写,而abstract必须被子类重写;

    如果类成员被abstract修饰,则该类前必须添加abstract,因为只有抽象类才可以有抽象方法;

    无法创建abstract类的实例;

    3、示例程序

      1 namespace Test0301
      2 {
      3     class Program
      4     {
      5         static void Main(string[] args)
      6         {
      7             Circle c1 = new Circle(7);
      8             Rectangle r1 = new Rectangle(12, 9);
      9             ShapeContainer sc = new ShapeContainer();
     10 
     11             sc.AddShape(c1);
     12             sc.AddShape(r1);
     13 
     14             c1.Update(1);
     15             r1.Update(7, 7);
     16 
     17             Console.WriteLine("Press any key to ecit...");
     18             Console.ReadKey();
     19         }
     20     }
     21 
     22     public class ShapeEventArgs : EventArgs
     23     {
     24         private double newArea;
     25 
     26         public ShapeEventArgs(double d)
     27         {
     28             newArea = d;
     29         }
     30 
     31         public double NewArea
     32         {
     33             get { return newArea; }
     34         }
     35     }
     36 
     37     public abstract class Shape
     38     {
     39         protected double area;
     40 
     41         public double Area
     42         {
     43             get { return area; }
     44             set { area = value; }
     45         }
     46 
     47         public event EventHandler<ShapeEventArgs> ShapeChanged;
     48 
     49         public abstract void Draw();//abstract和类定义的abstract对应,在派生类中必须实现
     50 
     51         //基类可以重载此函数,实现实际对象类型的此函数
     52         //此函数为事件句柄的实现函数
     53         protected virtual void OnShapeChanged(ShapeEventArgs e) 
     54         {
     55             Console.WriteLine("基类事件处理函数被{0}调用", this.ToString());
     56 
     57             EventHandler<ShapeEventArgs> handler = ShapeChanged;
     58             if (handler != null)
     59             {
     60                 handler(this, e); //this为调用此函数的派生类对象
     61             }
     62         }
     63     }
     64 
     65     public class Circle : Shape
     66     {
     67         private double radius;
     68 
     69         public Circle(double d)
     70         {
     71             radius = d;
     72             area = 3.14 * radius * radius;
     73         }
     74 
     75         public void Update(double d)
     76         {
     77             radius = d;
     78             area = 3.14 * radius * radius;
     79             OnShapeChanged(new ShapeEventArgs(area));
     80         }
     81 
     82         protected override void OnShapeChanged(ShapeEventArgs e)
     83         {
     84             //具体类的处理
     85             Console.WriteLine("Circle's radius changed!");
     86 
     87             //调用基类的函数
     88             base.OnShapeChanged(e);
     89         }
     90 
     91         public override void Draw()
     92         {
     93             Console.WriteLine("Drawing a circle");
     94             Console.WriteLine();
     95         }
     96     }
     97 
     98     public class Rectangle : Shape
     99     {
    100         private double length;
    101         private double width;
    102 
    103         public Rectangle(double length,double width)
    104         {
    105             this.length = length;
    106             this.width = width;
    107             area = length * width;
    108         }
    109 
    110         public void Update(double length, double width)
    111         {
    112             this.length = length;
    113             this.width = width;
    114             area = length * width;
    115             OnShapeChanged(new ShapeEventArgs(area));
    116         }
    117 
    118         protected override void OnShapeChanged(ShapeEventArgs e)
    119         {
    120             Console.WriteLine("Rectangle's radius changed!");
    121             base.OnShapeChanged(e);
    122         }
    123 
    124         public override void Draw()
    125         {
    126             Console.WriteLine("Drawing a rectangle!");
    127             Console.WriteLine();
    128         }
    129     }
    130 
    131     public class ShapeContainer
    132     {
    133         List<Shape> _list;
    134 
    135         public ShapeContainer()
    136         {
    137             _list = new List<Shape>();
    138         }
    139 
    140         public void AddShape(Shape s)
    141         {
    142             _list.Add(s);
    143             //订阅基类事件
    144             s.ShapeChanged += HandleShapeChanged;
    145         }
    146 
    147         private void HandleShapeChanged(object sender, ShapeEventArgs e)
    148         {
    149             Shape s = (Shape)sender;
    150 
    151             Console.WriteLine("Receicved event,Shape area is now {0}", e.NewArea);
    152 
    153             s.Draw();
    154         }
    155     }
    156 }
  • 相关阅读:
    JQuery 点击子控件事件,不会触发父控件的事件
    JQuery对Style和css设置
    2019vue学习视频(入门到精通)
    新建一个vue项目
    FIS3 构建
    node环境变量
    阿里云重启ssh
    msf 获取session 之后
    acccheck (暴力破解使用SMB协议的Windows密码)
    利用 Cut 指定输出内容
  • 原文地址:https://www.cnblogs.com/xyl-share-happy/p/4307400.html
Copyright © 2011-2022 走看看