.NET与面向对象
C#刨根究底:《你必须知道的.NET》读书笔记系列 - EdisonZhou - 博客园 (cnblogs.com)
第一章
1.1对象的旅程
(1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初始化,这样一个对象实体就完成了出生过程。
(2)旅程:在某种程度上就是外界通过方法与对象交互,从而达到改变对象状态信息的过程。
Person aPerson = new Person("yzh" , 22);
aPerson.ChangeName("yeyuotc");
(3)插曲:继承之访问修饰符
public:最高访问权限,公司的董事会具有最高的决策权与管理权;
protected:部门经理,具有对本部门的直接管辖权,面向对象中体现为子类继承纵向关系的访问约定;
internal:类似于公司的职能部门的职责,不管是否具有上下级关系,人力资源部都有管辖其他部门员工的能力;(面向对象中体现为同一程序集的访问权限,只要是隶属于同一程序集,对象即可访问其属性等,不管是否存在隶属关系;)
protected internal:副总经理,从横向到纵向都有管理权;
private:最低访问权,公司一般职员,管好自己即可;
接口实现多态
抽象类实现多态
(4)消亡:对象和人,有生必然也有死。
在.NET的世界中,对象的生命周期由GC来控制:GC管理所有的托管堆对象,当内存回收执行时,GC检查托管堆中不再被使用的对象,并执行内存回收操作;不被应用程序使用的对象,指的是对象没有任何引用。
公共语言运行时 (CLR) 概述 - .NET | Microsoft Learn
C#的三大难点之二:托管与非托管_c#非托管内存优缺点-CSDN博客
对与对象的理解:外界通过方法与对象交互,从而达到改变对象状态信息。
对象之间的交互方式就是设计模式
CLR提供了对象赖以生存的托管环境,语法像是规则(类型,继承,多态,垃圾回收等)
像是上层建筑,面向接口的编程就是以接口方式来抽象变化,从而形成体系。
对象就是在一定的约束与规则下,通过方法进行彼此交互大操作,从而达到改变自身状态的目的
1.2 继承
主要内容
1.密封类不可继承
2.继承关系中我们更多的关注的是共性而不是特性,因为共性是层次复用的基础,而特性是系统扩展
3.实现单继承,接口多继承
4.从宏观看,继承多关注于共通性,多态着眼于差异性
5.面向对象原则,多组合,少继承;低耦合,高内聚
1.将相同属性和特征的动物及其类别抽像分为一类,类与类的关系反应为相似/不相似的某种抽象关系
2.位于继承图的下层分别继承了上层的所有类别的特性
3.自上而下是逐渐具体化,下而上则是逐渐抽象,层与层的特性是向下递增的
(1)继承的分类:实现继承与接口继承
(2)继承的本质:面向对象中类与类之间的一种关系;继承的类称为子类、派生类;而被继承类称为父类、基类或超类;通过继承,使得子类具有父类的属性和方法,同时子类也可以通过加入新的属性和方法或修改父类的属性和方法建立新的类层次;
如上图的继承关系
Animal是所有类型的基类,构造成抽象类,抽象了普通行为 Eat(),ShowType(),ShowType()设置为虚函数,在chicken和Enagle中给出,在子类中实现虚函数的方法叫做动态绑定,是实现多态的基本机制。
Eagle类实现了接口继承,使得Eagle实例可以实现Fly这一特性,而IFlyable,实现了对象和行为的分离,无需使chicken会飞。
通过上图可知,通过继承可以轻易实现代码的复用和扩展,同时通过重载(overload),覆写(override),接口等方式实现了封装变化,隐藏私有信息,通过继承可以轻而易举的实现子类对父类共性的继承。
(3)实现继承与接口继承的区别:
抽象类适合于有族层概念的类间关系,而接口最适合为不同的类提供通用功能
接口多定义对象的行为;抽象类多定义对象的属性
版本式的问题最好以抽象类来实现
因为值类型是密封的,所以只能实现接口,而不能继承类
继承的本质体现在对象的创建过程:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
public abstract class Ainmals{
public void Eat()
{
Console.WriteLine("吃吃吃吃");
}
public abstract void showtype();
}
public class Bird : Ainmals
{
public string type = "Bird";
public override void showtype()
{
Console.WriteLine("类型:{0}", type);
}
private string color="red";
public string Color
{
get { return color; }
set { color = value; }
}
}
public class Chicken : Bird
{
public string type="Chicken";
public override void showtype()
{
Console.WriteLine("鸡鸡,{0}", type);
}
public void ShowColor()
{
Console.WriteLine("Color is {0}", Color);
}
}
class Program
{
static void Main(string[] args)
{
Bird bird2 = new Chicken();
Chicken chicken = new Chicken();
bird2.showtype();
Console.WriteLine("ss{0}", bird2.type); //会输出 "Bird"
chicken.showtype();
chicken.ShowColor();
string s = Console.ReadLine();
}
}
}
Bird bird=new Bird() 发生了什么
Chicken chicken=new chicken() ;
首先从底先上递归为父节点开内存空间,完成Sysrtem.Object创建,按照顺序完成整个父类及其本身字段的内存创建,并在字段从储存上由上而下排,父类和子类出现同名,会加以区别.
方法表的创建:在类第一次加载带哦AppDomain时完成,创建对象时只是将其附加成员TypeHandle指向方法列表在LoaderHeap上的地址,将对象与其动态的方法关联起来,因此方法表是先于对象而存在的。在创建时先复制父类的虚方法,然后和自身对比如果有覆写(override)存在,则以子类方法覆盖同名的父类方法,同时填加新方法。逐层递归到System.Object,开始有四个虚方法:ToString,Equals,GetHashCode,Finalize,
C#基础--应用程序域(Appdomain) - 小砖 - 博客园 (cnblogs.com)
继承是可以传递的,子类是对父类的扩展,必须继承父类方法,同时可以添加新方法
子类可调用父类方法和字段,父类不能调用子类方法和字段
虚方法如何实现覆写(override)操作,使得父类指针可以指向子类对象成员。
子类不光继承父类公有成员,私有也继承不过不被访问
new关键字在虚方法继承中的阻断作用
理解
Bird bird2=new Chicken();
//
Bird bird2-new Chicken();
Chicken chicken=new Chicken();
在内存上的布局是一样的,区别在于引用指针类型不同,不同指针在虚方法表中有不同的附加信息作为标志来区别其访问的地址区域,称为offset,不同类型的指针只能在特定的区域内执行,子类覆盖父类时会保证其访问地址区域的一致性
有一下原则:
1.关注对象原则:调用子类还是父类的方法,取决于创建的对象是子类对象还是父类对象而不是它的引用类型,引用类型的区别决定了不同对象在方法表中的不同访问权限。
2.执行就近原址:对于同名字段活方法,编译器是按照器顺序来查找引用的,首先访问里它最近的字段或方法
1.实现继承与接口继承
抽象类适合于有族层关系的类,接口适合为不同的类提供通用功能
接口多定义对象的行为,抽象类多定义属性
预计会出现的版本问题,可以创建“抽象类”.而向接口中添加新成员则会要求修改所有派生类,并重新编辑
值类型是密封的,所以只能实现接口,而不能继承类
2.聚合或者继承
聚合分为三种:无,共享,复合。 共享是class2不需要对class1负责,复合则class1会受class2的更改因此耦合
类与类,模块与模块,系统与系统都会发生交互,继承子类的对象确定于编译期,无法满足运行期才确定的情况,而类的聚合很好的补足了
(4)面向对象基本原则:多聚合,少继承;低耦合,高内聚;
Adapter模式实例-->类的Adapter模式与对象的Adapter模式相比,对象的Adapter模式通过聚合而非继承的方式来实现对原有系统的扩展,松散耦合,较少的新类型。
#region 类的Adapter模式
interface ITweetable
{
void ToTweet();
}
public class ChickenAdapter : Chicken, ITweetable
{
public void ToTweet()
{
Console.WriteLine("Chicken crows.");
}
}
#endregion
#region 对象的Adapter模式
public class BirdAdapter : ITweetable
{
private Bird _bird;
public BirdAdapter(Bird bird)
{
_bird = bird;
}
public void ShowType()
{
_bird.ShowType();
}
public void ToTweet()
{
//为不同的子类实现不同的ToTweet行为
}
}
#endregion
1.3封装
封装保证了类内部成员的安全性和可靠性
1.子段
field 通常定义为private,表示类的信息
2.属性
property public,表示类对外的成员,通过 get 和 set访问
对于编译器可以采用ILDASM工具查看编译后,莫个属性有 get;set;就会生成 get_属性名,set_属性名的方法,实现相印调用
3.方法
method 封装类的行为,提供类的对外表现,
隐藏系统实现细节,保证系统安全和可靠,保证代码模块化,提供稳定不变的对外接口
1.4多态
补充
公共语言运行时 (CLR) 概述 - .NET | Microsoft Learn