隐藏方法
概念理解:派生类使用 new 关键字将基类的数据成员或者方法做隐藏
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
Dog dog = new Dog();
dog.PrintPetName(dog.PetName);
}
}
public class Pet {
public string PetName = "十五";
public void PrintPetName(string name) {
Console.Write(name);
}
}
public class Dog:Pet{
new public string PetName = "十六";
new public void PrintPetName(string name) {
Console.Write("小狗的名字是"+name);
}
}
}
入口函数中使用派生类引用指向Dog的实例化对象是,调用到的是派生类中PrintPetName和PetName;这里如果使用基类的引用指向Dog的实例化对象,调用的则是基类里面的方法和属性;
多态
概念理解:将共有的属性和方法写在基类中会简化很多代码以后也会更好维护,为了派生类拥有自己的个性化,基类中在方法名之前添加virtual,派生类使用override重写该方法实现对该方法的拓展。
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
Dog dog = new Dog();
dog.PrintPetName(dog.PetName);
dog.PetEat();
}
}
public class Pet {
public string PetName = "十五";
public void PrintPetName(string name) {
Console.WriteLine(name);
}
public virtual void PetEat() {
Console.WriteLine("宠物吃东西");
}
}
public class Dog:Pet{
new public string PetName = "十六";
new public void PrintPetName(string name) {
Console.WriteLine("小狗的名字是"+name);
}
public override void PetEat() {
Console.WriteLine("狗吃肉");
}
}
public class Cat : Pet {
public override void PetEat() {
Console.WriteLine("猫吃鱼");
}
}
}
使用Dog的引用调用PetEat打印出来的是派生类中的内容(不管使用基类引用还是派生类的引用只要override种写 ,就调用override重写的内容)
构造函数(派生类)
1、执行派生类构造函数之前会隐式或显示调用基类的构造函数
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
Dog dog1 = new Dog();
}
}
class Pet {
public Pet() {
Console.WriteLine("基类构造函数");
}
}
class Dog : Pet {
//隐式调用
public Dog() {
Console.WriteLine("派生类构造函数");
}
//显示调用
//public Dog():base() {
// Console.WriteLine("派生类构造函数");
//}
}
}
断点先执行基类的
2、共通的数据成员也可以放在基类构造函数中赋值,这样会减少派生类的代码量
3、调用同一个类的不同构造函数可以使用 构造函数名:this() //显示调用的写法
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
Dog dog1 = new Dog("十五");
Cat cat1 = new Cat("十六");
}
}
class Pet {
protected string petName;
public Pet(string name) {
petName = name;
Console.WriteLine(petName);
}
}
class Dog : Pet {
public Dog(string name) : base(name) {
}
}
class Cat : Pet {
public Cat(string name) : base(name) {
}
}
}
抽象类抽象方法
1、使用abstract修饰的类或方法
2、有抽象方法的类一定要写成抽象类,抽象方法没有具体实现所以子类继承时一定会重写该抽象方法
3、抽象类不能被实例化
4、抽象方法相比虚方法因为没有实现更具个性化。
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
//Dog dog1 = new Dog("十五");
//dog1.PetEat();
//Cat cat1 = new Cat("十六");
//cat1.PetEat();
Pet[] pets = { new Dog("十五"), new Cat("十六") };
for (int i=0;i<pets.Length;i++) {
pets[i].PetEat();
}
}
}
abstract class Pet {
protected string petName;
public Pet(string name) {
petName = name;
Console.WriteLine(petName);
}
public abstract void PetEat();
}
class Dog : Pet {
public Dog(string name) : base(name) {
}
public override void PetEat() {
Console.WriteLine("狗狗吃骨头");
}
}
class Cat : Pet {
public Cat(string name) : base(name) {
}
public override void PetEat() {
Console.WriteLine("猫吃鱼");
}
}
}
密闭类和密闭方法
1、使用关键字 sealed 修饰的类和方法
2、sealed 修饰的类不能再被其他类继承
3、sealed 修饰的方法不能再被其他类重写
如果类被修改成Sealed将无法再继承下去
当Dog子类重写Speak()方法使用Sealed修饰时,继承自Dog的Schnauzer类无法再对Speak方法进行重写
接口
1、用于定义一系列没有具体实现的函数的引用类型 关键字是interface 接口只能用来被实现
2、可以多继承
3、接口中没有访问修饰符(默认就是public)
using System;
namespace ConsoleHide {
class Program {
static void Main(string[] args) {
Dog dog = new Dog();
dog.DogName();
dog.Speak();
dog.Eat();
//接口的引用指向强制转换的dog,只能调用接口中声明的方法
IPet pet = (IPet)dog;
pet.Speak();
pet.Eat();
Cat cat = new Cat();
cat.Speak();
cat.Eat();
}
}
interface IPet {
void Speak();
void Eat();
}
class Dog : IPet {
public void Eat() {
Console.WriteLine("狗吃骨头");
}
public void Speak() {
Console.WriteLine("汪汪");
}
public void DogName() {
Console.WriteLine("十五");
}
}
struct Cat : IPet {
public void Eat() {
Console.WriteLine("猫吃鱼");
}
public void Speak() {
Console.WriteLine("喵喵");
}
}
}
可空类型(nullable )
C#提供了一种可空类型,伴随某一具体的数据类类型出现表示变量在具体数据类型范围取值之外还可以添加一种空数据类型(可以用于数据库中某一字段值允许空值的情况)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleNullDataType
{
class Program
{
static void Main(string[] args)
{
double? num = null;
int? i = null;
}
}
}