C#基础——抽象类、接口;装箱与拆箱

C#基础——抽象类、接口;装箱与拆箱

1、抽象类

抽象类是一种特殊的类,它不能被实例化,只能用作其他类的基类。抽象类用于定义一组相关的类的共同行为和属性。

定义一个抽象类

//区别:定义了一个抽象的方法    
//由virtual 换成了 abstract,都是代表虚方法,需要让子类重新来实现的,区别在于abstract不需要展开。  
public abstract class Pet {
    public String Name;
    public String Health;
    public String Gender;
    public abstract void Eat();
    public abstract void ToHospital();
}

//如果只描述抽象类不赋值,代表空指针
Pet pet; 
//Pet pet2 = new Pet(); //抽象类是不能直接创建本类实例的

定义一个抽象类的派生类

//注意:凡是继承抽象类的当前类,都需要把基类中描述的方法实现了,否则会报错  
public class Dog : Pet {
   public override void Eat() {
     Console.WriteLine("狗子喜欢吃骨头");
   }
   public override void ToHospital() {
     Console.WriteLine("健康也很重要");
   }
}

Dog dog;
//使用了基类指向了派生类对象
pet = new Dog();
//as 将一个对象转成另一个对象,如果转换失败则返回null
dog = pet as Dog;
if (dog != null)  dog.Eat();
else Console.WriteLine("转换失败了");

注意:凡是继承抽象类的当前类,都需要把基类中描述的方法实现了,否则会报错

2、接口 interface

接口(interface)是一种定义了一组方法、属性、事件或索引器的合同。接口定义了类或结构体应该实现的成员列表,用于描述对象的行为或能力。

// 接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的
//当需要继承的目标是多个的时候,可以考虑使用接口
public interface A {
  //接口的方法只声明不实现,表示需要在派生类中实现
  void Method1();
}

public interface B : A {
   //只有类继承自接口的时候接口的方法需要实现,如果是接口继承自接口,则不需要实现
   void MethodB();
}

//在这里(派生类)中实现接口中的方法
class Man : A, B { 
   public void Method1() {
     Console.WriteLine("这是继承自接口A的方法");
   }
   public void Method2() {
     Console.WriteLine("这是自身的方法");
   }
   public void MethodB() {
     Console.WriteLine("这是继承自接口B的方法");
   }
}

接口中的成员

接口中应该只包含方法的声明,不能有方法的实现

接口中不能出现构造函数

接口中不能包含实例字段,也不能包含运算符重载

接口中不允许声明成员修饰符,默认只有一个就是 public

public interface ISpeakLanguge {
    //接口中应该只包含方法的声明,不能有方法的实现
    void Speak();
    //接口中不能出现构造函数
    //public ISpeakLanguge(){}

    //接口中不能包含实例字段,也不能包含运算符重载
    //int a;
    //接口中不允许声明成员修饰符,默认只有一个就是 public
    //private void aa(string a) { }; //报错
}

public class ChinesePeople : ISpeakLanguge {
   //如果一个类继承了接口,那么首先要把接口中声明的方法实现,否则会报错
   public void Speak() {
     Console.WriteLine("中国人说中国话。");
   }
}

抽象类和接口的区别

两者的区别 抽象类 接口
实现方式 通过继承来实现 通过实现来实现的
实现限制 一个类可以同时继承抽象类并实现接口,但只能继承一个抽象类 一个类可以实现多个接口
成员类型 可以包含具体方法的实现,也可以包含抽象方法和属性 只能定义抽象方法、属性、事件和索引器,不能包含具体实现
构造函数 可以有构造函数 不能有构造函数
默认实现 可以提供成员的默认实现,派生类可以选择性地重写或调用基类的实现 没有默认实现,实现接口的类必须提供所有成员的具体实现
目的和设计理念 用于表示一种通用的基类,它可以包含代码重用和共享状态的能力 用于定义一种契约,规定了类应该具有的行为,强调了多态性和代码的松耦合性

装箱(Boxing)和拆箱(Unboxing)是与数据类型转换相关的概念

3、装箱:将一个值类型的数据转换为对应的引用类型。当需要将值类型赋值给引用类型或者作为参数传递给接受引用类型的方法时,会发生装箱操作。

//在装箱过程中,系统会创建一个新的引用类型对象,并将值类型的数据复制到该对象中。
int value = 10;
object boxedValue = value; // 装箱操作

4、拆箱:将一个装箱后的引用类型对象转换为对应的值类型数据。当需要从引用类型中获取值类型数据或将装箱后的对象赋值给值类型变量时,会发生拆箱操作。

//在拆箱过程中,系统会检查引用类型对象是否实际上装箱了值类型数据,并将其提取出来。
object boxedValue = 10; // 装箱操作
int value = (int)boxedValue; // 拆箱操作

注意:

拆箱操作需要进行显式的类型转换,以确保拆箱后的数据类型正确。如果拆箱的对象并非装箱时的值类型,或者装箱对象为 null,那么在拆箱时会抛出异常。

拆箱和装箱的过程会涉及数据的复制和类型转换,因此可能会对性能产生一定的影响。在需要频繁操作值类型数据的场景中,尽量避免不必要的装箱和拆箱操作,以提高代码的执行效率。

你可能感兴趣的:(C#,c#,开发语言)