C#语法相关(三)

多态
先来看一下例子:
using System;
 class Fruit
{
    public void PutFruit()
    {
        Console.WriteLine("父类的PutFruit方法被调用");
    }
}
class Apple:Fruit
{
    public  void PutFruit()
    {
        Console.WriteLine("子类的PutFruit方法被调用");
    }
}
class Program
{
    static void Main(string[] args)
    {
        Fruit fruit = new Apple();
        fruit.PutFruit();//调用的是父类的方法
    }
}
父类Fruit和子类Apple有一个相同的方法PutFruit,像我们知道,如果是父类对象调用PutFruit,那么就是父类的PutFruit方法被执行,子类对象调用,就是子类的PutFruit方法被执行。
而上面那个例子,用父类定义了fruit,然后用子类来实例化,这样再调用PutFruit,执行的是子类的方法,还
是父类的呢。答案是父类的。
而多态呢,在这个情况下调用的是子类的方法,也就根据父类指向子类对象的不同,而调用相应子类的PutFruit方法,不过多态得用虚函数来实现。
也就是下面这个模式:
using System;
 class Fruit
{
    public  virtual void PutFruit()//虚方法,用于多态
    {
        Console.WriteLine("父类的PutFruit方法被调用");
    }
}
class Apple:Fruit
{
    public  override void PutFruit()//override和父类虚函数相呼应。
    {
        Console.WriteLine("Apple子类的PutFruit方法被调用");
    }
}
class Banana:Fruit
{
    public override void PutFruit()
    {
        Console.WriteLine("Banana子类的PutFruit方法被调用");
    }

}
class Program
{
    static void Main(string[] args)
    {
        Fruit fruit = new Apple();
        fruit.PutFruit();
        fruit = new Banana();
        fruit.PutFruit();

    }
}
其中被override修饰的方法,在父类中与其相同的方法,必须被virtual或abstract关键字修饰,而父类中被virtual
修饰的方法,它子类对应的方法,也必须被virtual修饰,不然无法实现多态。另外这也是方法的重写。或者说是通过方法的重写来实现

多态的。
抽象类。
用abstract关键字修饰的类,就叫做抽象类,抽象类里可以有抽象方法,也可以没有。它们之间的区别就是
方法前有没有abstract关键字,而且抽象方法没有执行语句,因为它本身不会被调用,只是给子类重写的。
另外,抽象类不能被实例化。
看下例:
using System;
abstract class Fruit//抽象类
{
     public abstract void PutFruit();//抽象方法
}
class Apple:Fruit
{
    public  override void PutFruit()//override和父类虚函数相呼应。
    {
        Console.WriteLine("Apple子类的PutFruit方法被调用");
    }
}
class Banana:Fruit
{
    public override void PutFruit()
    {
        Console.WriteLine("Banana子类的PutFruit方法被调用");
    }

}
class Program
{
    static void Main(string[] args)
    {
       Fruit fruit = new Apple();//new Fruit()是无法通过的,抽象类不能实例化
       fruit.PutFruit();
       fruit = new Banana();
       fruit.PutFruit();
    }
}

委托
  因为C#没有指针这个概念,所以函数指针也没有,那么委托就是代替函数指针的,它的存在跟C++函数指针一样。
先来看一下C++函数指针的例子:
#include<iostream.h>
void OutApple(int Num)
{
 cout<<Num<<endl;
}
typedef void (*pOutApple)(int Num);

void (* poa)(int Num);
int main(int argc, char* argv[])
{
    pOutApple pOutAle=OutApple;
 pOutAle(550);
 poa=OutApple;
 poa(650);
 return 0;
}

上面void (* poa)(int Num)这一句就是定义了一个函数指针,指向OutApple函数,
而typedef void (*pOutApple)(int Num)这一句,就是给函数类型定义取别名,这样pOutApple就是一个OutApple函数指针类型,用pOutApple定义的变量,就是一个可以指向OutApple函数的函数指针。
而C#的委托就是跟这个相关,可以这么说,它是用delegate代替了C++的typedef。
 例子:C#委托的定义
using System;
delegate void pOutApple(int Num);//定义委托
class Apple
{
    public void OutApp(int Num)
    {
        Console.WriteLine("{0}", Num+500);
    }

}
class Program
{
    static void OutApple(int Num)
    {
        Console.WriteLine("{0}", Num);
    }
   
    static void Main(string[] args)
    {
        pOutApple pOutAle = OutApple;//指向OutApple方法

       //另外指向OutApple方法,也可用这种:pOutApple pOutAle=new pOutApple(OutApple);实例化
        pOutAle(500);
        Apple apple = new Apple();
        pOutAle = apple.OutApp;//指向Apple类里的OutApp方法
        pOutAle(500);
    }
}

多播委托就是可以同时执行多个方法,用'+'号把实例化的委托合并起来。
看下例:
using System;
delegate void pOut();//定义委托

class Program
{
    static void FirOut()
    {
        Console.WriteLine("第一个FirOut方法");
    }
    static void SecOut()
    {
        Console.WriteLine("第二个SecOut方法{0}");
    }
    static void ThiOut()
    {
        Console.WriteLine("第三个ThiOut方法");
    }
    static void Main(string[] args)
    {
        pOut pot1 =new pOut(FirOut);//第一个FirOut方法
        pOut pot2 = new pOut(SecOut);//第二个SecOut方法
        pOut pot3 = new pOut(ThiOut);//第三个ThiOut方法
        pot1 += pot2;//合并
        pot1 += pot3;
        pot1();//一起调用三个方法
        Console.WriteLine("删除掉pot2,也就是SecOut方法");
        pot1 -= pot2;//删除一个方法
        pot1();//调用两个方法
    }
}
记住,合并的方法必须是一致的,它的参数,返回值等。


接口
接口的特性跟类很相似,可以被继承,里面也有方法,这里说一下它们的区别。
接口里不能有普通的成员变量(字段),但可以有属性成员(也就是set,get模式的变量),但在接口中,这些成员,方法,或者属性成员,都只是一个空壳,没有实际实现。
都是由继承它的类,或者结构体来具体实现的。
C++中,一个类可以继承多个类,但C#中只可以单继承,似乎关于类继承方面C#没有C++灵活,但C#的类可以继承多个接口,算是弥补了这个不足吧。
例子:接口的实现
using System;
//第一个接口IApple,interface关键字定义接口
interface IApple
{
    void OutApple(int Num);
}
//第二个接口IBanana
interface IBanana
{
    void OutBanana(int Num);
}
//继承两个接口,类里面必须实现继承的接口方法
class Outnum:IApple,IBanana
{
    //实现接口方法
    public void OutApple(int Num)
    {
        Console.WriteLine("{0}", Num);
    }
    public void OutBanana(int Num)
    {
        Console.WriteLine("{0}",Num);
    }

}
class Program
{
    static void Main(string[] args)
    {
        Outnum outnum = new Outnum();
        outnum.OutApple(500);
        outnum.OutBanana(1000);
    }
}

显式接口
 怎么定义显式接口,在继承接口的类中,用接口成员全权名的方式定义接口,所谓全权名,比如接口IBanana,
它里面的OutBanana方法的全权名就是IBanana.OutBanana;
那么显式接口里面的方法是怎么样调用的呢,通过接口调用,也就是接口定义的对象通过继承它的类来实例化,再调用接口里的方法。
例子:显式接口的定义以及使用
using System;
//第一个接口IApple,interface关键字定义接口
interface IApple
{
    void OutApple(int Num);
}
//第二个接口IBanana
interface IBanana
{
    void OutBanana(int Num);
}
//继承两个接口,类里面必须实现继承的接口方法
class Outnum:IApple,IBanana
{
    //显式接口的定义,显示接口的方法不能用public修饰
     void IApple.OutApple(int Num)
    {
        Console.WriteLine("{0}", Num);
    }
    void IBanana.OutBanana(int Num)
    {
        Console.WriteLine("{0}",Num);
    }

}
class Program
{
    static void Main(string[] args)
    {
        IApple iapple = new Outnum();
        iapple.OutApple(500);
        IBanana ibanana = (IBanana)iapple;//其实指向的还是new Outnum()
        ibanana.OutBanana(1000);
    }
}
另外接口不能通过继承类的方式来继承,例如一个Outnum类继承了一个接口IApple,那么Program类继承Outnum类的话,Program类里是没有IApple里的方法的,如果要使用,还需要自己来继承接口,并实现。

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bczheng1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值