1.封装,继承,多态
三个特性主要目标:重用性(安全性)、灵活性和扩展性。
封装 可以通过 以下 方式实现:
* (方法不一定是属性 ; 属性一定是 方法!)
属性(Property):通过Get和Set方法实现对数据的读写操作,
并可以在进行数据读写时添加自定义的逻辑。
在C#中,属性可用于将实例变量封装到类中
访问修饰符:C#中有四种访问修饰符: public、private、protected和internal。
这些访问修饰符 可用于控制类中数据和方法的访问权限
方法:实现细节可以隐藏起来并只暴露实现所需的最小接口。
这样可以保证类的内部细节安全,并且仅在类的外部提供必要的接口
继承:
什么是继承?
* 1.一个类继承另一个类其中被继承的类(父类、超类、基类) 继承的类(子类、派生类)
*** ⒉.继承关系建立后子类拥有父类的属性和方法反之父类不继承子类属性和方法。
* 父类 的 私有成员 子类无法使用。
3.子类继承父类的实例成员 ■ 子类不继承父类的静态成员
4.继承的作用:解决类与类直接属性或者方法重复的问题
5 .C#中类与类之间是单继承关系(子类只能同时 继承一个 父类);
利用接口实现多继承(后续讲)
** 6.继承的格式 A类(子类): B类(父类)
7.创建子类对象时,系统默认先调用父类构造方法,然后再调用子类构造方法
8.当父类有有参构造方法时,如果子类有构造方法(无参或有参) ,
要求父类必须有一个无参构造方法。
9. 一个父类可以被 多个子类继承 子类可以间接继承 父类
10.object 是 所有类 的父类; 如果一个类没有明确继承关系、
默认继承于object类(基类)
11.当 父类 有 有参构造方法时,必须提供一个无参构造函数 供子类调用
12.子类在调用其有参或者无参构造函数时,
默认调用父类的无参构造函数如果想要 调用父类有参构造函数使用
在子类构造函数后添加:base(参数名)
多态:
即 一个 接口,多个功能 同一种操作 作用于不同的 对象,
* 可以有不同的解释,产生不同的执行结果
包含:
重写抽象类接口重载
// 重载
在一个类中或者子类中函数名相同,参数类型或者顺序不同构成重载,与返回类型无关
重写:
1.在子类和父类中,子类中的方法名称和父类方法名称相同,参数相同
2.使用关键字virtual,将父类的方法标记为虚方法,
用override 关键字,虚方法可以被子类重写
3.重写是合法的覆盖
4.重写和覆盖为了扩展父类的功能
5.重写必须和父类中的方法一样(参数 方法名 访问权限 返回值类型)
实现父类功能 的调用:
internal class Boy : Man
{
public Boy(){}
public Boy(int manID):base(manID)
{
ManID = manID;
}
public void MothodTest()
{
//实现父类的功能调用
base.MothodTest();
//实现子类的功能扩展
Console.WriteLine("Boy中的MothodTest");
}
}
2.抽象类
抽象类
1关键字 abstract
2.不能被实例化 不能创建对象
3.普通类继承抽象类 抽象类可以继承抽象
4.抽象类可以包括抽象方法和抽象属性但是不能定义抽象字段,或者能定义普通方法属性字段
5.普通类继承了具有抽象成员的 抽象类 必须在其内部重写抽象的抽象成员 (使用override)
6.静态成员不能定义为抽象:
× AbstractClass abstractClass = new AbstractClass();
在 C# 中,抽象类(Abstract Class)是一种类,它用于提供其他类的通用模板或基类。抽象类本身不能被实例化,而是被设计用来作为其他类的基类,其中可能包含抽象方法、虚拟方法和普通方法。以下是关于抽象类的主要特点和使用方式:
-
抽象类的声明:抽象类使用
abstract
关键字进行声明。它不能直接实例化,只能被继承。public abstract class Shape { // 抽象类可以包含抽象方法、虚拟方法和普通方法 public abstract double CalculateArea(); // 抽象方法 public virtual void Display() // 虚拟方法 { Console.WriteLine("This is a shape."); } }
-
抽象方法:抽象类可以包含抽象方法,这些方法没有实现代码,只有方法签名。子类必须实现抽象方法,否则它们也必须被声明为抽象类。
-
虚拟方法:抽象类可以包含虚拟方法,这些方法有默认实现,但可以在派生类中重写。
-
派生类:其他类可以继承抽象类,并实现其抽象方法。如果一个类继承了抽象类,它必须提供实现所有抽象方法,除非它自身也声明为抽象类。
public class Circle : Shape { public double Radius { get; set; } public Circle(double radius) { Radius = radius; } public override double CalculateArea() { return Math.PI * Math.Pow(Radius, 2); } }
-
实例化:虽然抽象类不能被直接实例化,但你可以创建抽象类的具体派生类的实例,并使用它们。
Shape myShape = new Circle(5.0); double area = myShape.CalculateArea(); myShape.Display();
抽象类用于建模具有共享行为和属性的一组相关类,并提供一种强制要求派生类实现特定行为的机制。这有助于实现多态性和通用性,使代码更易于维护和扩展。
3.重写、重载、覆盖
重写:
1.在子类和父类中,子类中的方法名称和父类方法名称相同,参数相同
2.使用关键字 virtual,将父类的方法标记为虚方法(父类允许子类覆盖方法的标签)
用 override 关键字,虚方法可以被子类重写
3.重写是合法的覆盖
4.重写和覆盖为了扩展父类的功能
5.重写必须和父类中的方法一样(参数 方法名 访问权限 返回值类型)
重写和重载和覆盖
1.重写是合法的覆盖
2.重载可以在本类和子类中实现 重写只能在继承关系中实现
3.重载和重写方法名字要相同 ,重载的参数的类型和个数和顺序要不一样 重载的访问权限和返回值类型和静态非静态无关,
重写必须和父类中的方法一样(参数 方法名 访问权限 返回值类型)
4.重写和重载都是多态的体现
-
重载(Overloading):
- 重载是指在同一个类中定义多个方法或构造函数,它们具有相同的名称但有不同的参数列表(参数的类型或数量不同)。
- 重载允许你为同一操作提供多个不同版本,根据传递的参数来选择合适的方法。
- 重载不涉及继承,而是在同一类中创建多个方法。示例:
public class Calculator { public int Add(int a, int b) { return a + b; } public double Add(double a, double b) { return a + b; } }
-
重写(Overriding):
- 重写是指在派生类中定义一个与基类中的虚拟方法(使用
virtual
修饰符)具有相同名称和签名的方法。 - 重写用于修改或扩展基类中的方法的行为,允许派生类提供特定实现。
- 重写方法必须使用
override
关键字进行标记,并且必须在派生类中重新实现基类中已定义的虚拟方法。示例:
public class Shape { public virtual void Draw() { // 基类中的默认绘制操作 } } public class Circle : Shape { public override void Draw() { // 派生类中重写的绘制操作 } }
- 重写是指在派生类中定义一个与基类中的虚拟方法(使用
-
覆盖(Hiding):
- 覆盖是指在派生类中定义一个与基类中的方法具有相同名称但没有使用
override
关键字的方法。 - 这会隐藏基类中的方法,而不是修改它。派生类的方法并不会替代基类的方法,而是存在于派生类中,可能导致对基类方法的访问困难。
- 覆盖主要用于意外隐藏或误用基类方法的情况,应该谨慎使用。示例:
public class BaseClass { public void Foo() { Console.WriteLine("BaseClass.Foo"); } } public class DerivedClass : BaseClass { public new void Foo() { Console.WriteLine("DerivedClass.Foo"); } }
- 覆盖是指在派生类中定义一个与基类中的方法具有相同名称但没有使用
总结:
- 重载是在同一类中创建多个方法,它们具有相同名称但不同的参数。
- 重写是在派生类中重新实现基类中的虚拟方法,以修改或扩展其行为,使用
override
关键字。 - 覆盖是在派生类中创建一个与基类中方法具有相同名称但没有使用
override
关键字的方法,可能会隐藏基类方法。应该慎重使用覆盖,通常是一种不推荐的做法。
4.this, base
this
代表当前类的对象
this关键字只能在实例构造函数、实例方法或实例访问器中使用
base:
base关键字用于从派生类中访问基类的成员;
派生类对象调用基类构造函数;
调用基类上已被重写的方法
不能从静态方法中使用base关键字,base关键字只能在实例构造函数、实例方法或实例访问器中使用
-
this
关键字:this
用于引用当前对象的实例成员,通常用于区分实例变量和方法参数或局部变量之间的名称冲突。this
可以用于调用当前对象的构造函数,实现构造函数的重载。
public class MyClass { private int value; public MyClass(int value) { this.value = value; // 使用 this 访问实例变量 } public void DisplayValue() { Console.WriteLine(this.value); // 使用 this 访问实例变量 } }
-
base
关键字:base
用于访问基类的成员,通常在派生类中用于调用基类的构造函数或访问基类的虚拟方法。base
主要用于确保在派生类中正确初始化基类的状态,以及在派生类中扩展基类的行为。
public class BaseClass { protected int value; public BaseClass(int value) { this.value = value; } } public class DerivedClass : BaseClass { public DerivedClass(int value, int derivedValue) : base(value) { // 使用 base 调用基类构造函数 // 完成基类的初始化 // 可以访问 base.value 和 this.value this.value += derivedValue; // 扩展基类的行为 } }
总结:
this
用于访问当前对象的实例成员和调用构造函数。base
用于访问基类的成员和调用基类的构造函数。- 这两个关键字有助于确保代码的清晰性,尤其是在派生类中扩展和修改基类的行为时,它们是很有用的。