面向对象的一点简易理解

cls1里有一个aa() 假设所有成员都是public;
如果cls2继承cls1时
cls1 my = new cls1();my.aa();
这个好说当然是执行cls1的aa方法啦(这不废话嘛^_^)
别丢板砖
继续
mycls2 my = new mycls2();my.aa();
这个比上面稍有改变
第一种情况:cls2中没写aa();
    执行的是cls1的aa方法
    因为它本身继承了cls1的方法 而他自己又没有重写父类的aa方法
第二种情况:cls2中写了名字为aa的方法并且前面加new关键字
    执行的是cls2的aa方法
第三种情况:cls2中写了名字为aa的方法并且前面加override关键字
    执行的是cls2的aa方法
    貌似case2和case3是一样的,其实不一样
    用new关键字:
        会把父类的方法废掉,父类的同名方法从此与他无关 以子类为主 你可以写
        跟父类名字一样参数不一样的方法,相当与重载
    用override关键字:
        方法重写,父类必须要有同名方法并且带virtual关键字
        并且重写的时候要遵循父类同名方法的参数

如果在cls2的aa方法中写aa();会造成死循环 导致堆栈溢出
但是如果想在cls2中访问cls1的aa方法怎么办呢^_^
用base.aa();就行啦
this关键字相当于当前实例本身
base关键字相当于被继承的父类
在一个类中方法同名参数不同叫重载
父类与子类中方法重名叫重写(并且参数也要一样^_^)

mycls1 my = new mycls2();
这种变化较大(别被前面的cls1迷惑了)虽然实例是cls2实际上依然可以调用
父类的所有的方法 跟上面一种情况一样
如果cls2没写任何代码依然执行cls1的aa方法
当前的引用是cls1的 cls2里定义的成员会访问不到,继承自cls1的成员可以访问
如果 用override重写则能访问到 以前的什么工厂设计模式中经常这么弄

不管咋变 都是看他的引用 引用属于哪个个cls 那么 实例化的对象继承自那个cls的所有public成员(如果被重写了就改为重写的成员)都可以被外部访问
但是那个实例化对象自己另外的成员不能被外部访问

如果引用跟  实例化的对象属同一cls
如果重写了则调用子类的方法
没重写则调用父类的方法 就这么简单

两个互不相干的cls(哪怕在同一命名空间) 要想访问对方的成员 ,那个成员必须是public
如果是不同命名空间 或者项目 要想在其他的项目中 实例化那个cls,那个cls必须是public



要养成面向对象编程的习惯
到处都要用的变量 放到外面作为成员,
不要所有的业务逻辑全都一股脑写成一个个的方法堆起
不要访问级别 继承的什么都不管 全部写成 javascript函数形式的东西
这样的话跟oop就有点脱节了
可能开始不太习惯 但是你会发现这会给你设计程序带来莫大的好处

这些都是oop的基本常识 但是只要运用得当 也可以让你的程序运行得更好,别太在乎那些花哨的设计模式 并不是那些东西没用
只是别贸然模仿

时隔今日 又来这篇博文上添砖加瓦。

上次张翔同学说不知道什么情况下新建一个类 什么情况下拓展,一时我也不知如何回答他。上周参考了以前的报价软件代码思想做出一个例子 正巧可以做说明:

这里有个功能 要做各种报表导出。 然后就建一个 报表导出基类:

 1 class ReportExport
 2     {
 3         string reportName;
 4         string reportFullName;
 5         ProjectAdapter ada;
 6         //初始化模板名字 文件保存目录 和适配器
 7         public ReportExport(string _reportName, string _reportFullName)
 8         {
 9             reportName = _reportName;
10             reportFullName = _reportFullName;
11             ada = MyApp.Instance.AdapterFlyWeight.GetProjectAdapter();
12         }
13 
15         //进行数据适配
16         public virtual void AdaptiveToData()
17         {
18             dataModels = new List<BaseModel>();
19             templateNames = new List<string>();
20             sheetNames = new List<string>();
21         }
22 
23         protected List<BaseModel> dataModels;
24         protected List<string> templateNames;
25         protected List<string> sheetNames;
26         
28         //进行导出动作
29         public virtual bool Export()
30         {
31             ada.ExoprtToFile(dataModels, templateNames, sheetNames, reportFullName);
32             return true;
33         }
34     }
 然后我有个特定的名字叫甲方文件 的报表 继承这个基类
 1 class ReportJiafang:ReportExport
 2     {
 3         public ReportJiafang(string  reportJiafangFullName)
 4             : base("甲方文件报表",reportJiafangFullName)
 5         { }
 6 
 7         public override void AdaptiveToData()
 8         {
 9             base.AdaptiveToData();
11             dataModels.Add(App.Instance.CurrentProject);
12             dataModels.Add(App.Instance.CurrentProject);
13 
14             templateNames.Add("甲方文件报表汇总表");
15             templateNames.Add("甲方文件报表明细表");
16 
18             sheetNames.Add("甲方文件总表11");
19             sheetNames.Add("甲方文件明细表22");
20         }
21     }

你看我初始化的时候 自动调用基类的构造方法 名字默认传“甲方文件报表” ,因为从类的名字上已经体现了,然后只需要传保存文件路径通过base传递给基类构造函数。

然后是通过 AdaptiveToData进行数据适配处理 ,不同的报表是不一样的。所以这里需要对方法进行重写。

然后调用的时候:

1 ReportJiafang rpt =new ReportJiafang("d:\aaa.xlsx");
2 
3                     rpt.AdaptiveToData();
4                     rpt.Export();

你看继承和面向对象编程就是有这个威力 ,对同类型的工作进行归纳放到基类处理。

而在外部调用又实现了保证接口和流程的统一性。而让子类又能够拥有各自的细节化处理。

你如果用面向过程的思维方式来编程 是不是要low很多 特别是处理这种问题的时候。

 是不是体现了一种辩证与统一的思想
原文地址:https://www.cnblogs.com/assassinx/p/3718143.html