面向对象的三大特征:封装、继承、多态

时间:2022-04-14 21:57:22

 面向对象的三大特征:封装、继承、多态

本系列文章包括:

1 什么是面向对象?

2 为什么需要面向对象?

3 面向对象的基本概念

4 面向对象的三大特征

5 面向对象程序设计实例

6 面向对象程序设计原则

7 面向对象程序设计注意问题

8 总结、参考资料

面向对象的三大特征

  • 封装(Encapsulation)

封装,可以望文生义,即将东西封装起来,不让别人知道,当然,自己可以知道,指定信得过的人也可以知道。

 

封装将数据和行为封装起来,并对对象的使用者隐藏了数据的实现方式。

其实,一个对象就是封装了数据和操作这些数据的代码的逻辑实体。

在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。这就为对象内部数据提供了保护的作用,防止被意外修改。

 

好处:

1提高重用性(封装)

2提高可靠性(隐藏)

3方便对象的使用者使用(隐藏了复杂性)

 

  • 继承

现实世界中,很多东西都不是相互孤立的,它们往往具有相同的特征,也存在差异。

 面向对象的三大特征:封装、继承、多态

上图反应了人类的派生关系。最高层往往具有最普遍的特征,越往下层越具体,并且下层包含上层的特征。

在程序设计中,这种关系叫做继承。一个类从另外一个类派生出来,派生类继承了父类的所有特性,并且可以添加自己的特性。通过继承所创建的新类叫做子类(或派生类),被继承的类叫做父类(或基类、超类),继承的过程是从一般到具体的过程。

继承是is-a的关系,是一种用于表示特殊与一般的关系。

在考虑使用继承时,如果两个类的关系是“is-a”的关系,即说“XXX是XXX”成立的话,继承关系就成立了。如:说“男人是人”,说得通吧;要是说“王八是人”,看人家不!@&#%#¥。

在面向对象中,继承是非常优秀的语言机制,有如下优点:

1提高代码的重用性;

2代码共享,减少创建类的工作量,因为,每个子类都拥有父类的属性和方法;

3提高代码的可扩展性;

4子类可以形似父类,又可以异于父类。

当然,也有缺点:

1继承是入侵的。只要继承,就必须拥有父类的所有属性和方法;

2降低了代码的灵活性。子类必须拥有父类的所有属性和方法,让子类的*世界多了约束。试想,要是“老爹”是个品行不正,是个酒鬼,“儿子”被坑大了。

3增强了耦合性。当父类被修改时,必须考虑子类的修改,可能导致大片的代码需要重构。

 

  • 多态(polymorphisn)

所谓多态,就是父类型的引用可以指向子类型的对象(或接口类型的引用可以指向实现该接口的类的实例)

如: 

?
//动物
public  class  Animal {
     //动物都会
     public  void  cry() {
         System.out.println( "(动物叫)" );
     }
}
 
 
//狗,继承于动物
public  class  Dog extends  Animal {
     //狗有它自己的叫法
     @Override
     public  void  cry() {
         System.out.println( "汪汪" );
     }
}
 
public  class  Test {
     public  static  void  main(String[] args) {
         //Dog dog = new Dog();
         //dog.cry();       
         Animal animal = new  Dog(); //父类型的引用可以指向子类型的对象
         animal.cry(); //输出:汪汪
     }
}

  

实现多态,有二种方式:覆盖、重载。

覆盖:是指子类重新定义父类的方法。

重载:是指方法名相同,参数列表不同。

可以这么理解:

覆盖,不但不用祖宗那套功夫,而且还自己创一套新的代替祖宗那套;

重载,你是你,我还是我。

覆盖,为纵向关系;重载,为横向关系。

接下来应该注意了。

1其实,重载的概念并不属于“面向对象编程”,重载的实现是编译器根据函数不同的参数列表,对同名函数的名称进行修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如有2个同名函数function func(p:integer):integer和function func(p:string):integer,那么编译器做过修饰后的函数名称可能是int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住是静态)。也就是说,它们的地址在编译期就绑定了(早绑定)。因此,重载和多态无关!

 

2真正和多态相关的是“覆盖”。当子类重新定义了父类的函数后,父类指针根据赋给它的不同的子类指针,动态(记住是动态)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。

 

3结论:

a重载只是一种语言特性,与多态无关,与面向对象也无关。引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚邦定,它就不是多态。”

b多态是晚绑定;

c多态是一种运行期行为,不是编译器的行为;

d不要把重载理解为多态,重载是编译时就确定的;

e构成多态的条件:继承、重写、父类引用子类的对象。

 

4那么,多态的作用是什么呢?

我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类)。它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用。多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

 

 

 

 

 

分类:  面向对象
标签:  面向对象封装继承多态

在Winform开发框架中实现对数据库的加密支持

在很多情况下,我们需要对数据库进行加密,特别是Access数据库、Sqlite数据库,这些直接部署在客户端的数据,因为数据也是客户的资产,数据库总是存在很多相关的秘密或者重要的业务数据,所以一般来说,数据库是比较敏感的。由于我的Winform开发框架数据库访问模块中采用了EnterpriseLibrary模块,因此其实也可以使用其中的Crytography Application Block进行加解密处理。

由于不想引入太多这些额外的模块,或者为了简化客户端的配置考虑,直接在EnterpriseLibrary模块内部对数据库连接字符串,增加密码部分,也是一个有效的方法,本文通过介绍这种方式,实现对加密Access数据库连接字符串的处理,并能顺利访问带密码的Access数据库。

1、数据库选择

如果要加密的是Access数据库,必须选择Access2007以上版本,这个版本的密码是经过128位的特殊处理,目前好像还是比较难破解,也好像没有找到合适的破解工具,如果是Access2000,那破解密码的工具真是多了去的了。

Access2007版本的数据库引擎,一般没有安装Office2007的电脑,是需要特别安装AccessDatabaseEngine这个驱动的。否则会提示“The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.”(未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序)的错误。到微软网站下载对应版本的驱动即可。

如果要加密的是Sqlite数据库,那么也是可以比较有效的,他的密码也是比较难于破解的。

上面两种客户端数据库,打开后先通过软件本身的功能进行加密,密码我们在开发初期就设定即可,客户一般不需要了解,他们或者其他人员复制出去,也无法单独使用,确保了数据库的安全性。

2、数据库加密处理

1)Access的数据库加密 

如果是对Access的数据库加密,记住选择Access2007以上的格式,然后以独占方式打开Access文件,如下图所示。

面向对象的三大特征:封装、继承、多态

然后在数据库工具选项里面,选择用密码进行加密,在弹出的对话框输入你的密码即可。

面向对象的三大特征:封装、继承、多态

Office2007的密码强度还是不错的,至少我找了好几个工具,没能顺利破解出我的密码内容。

2)Sqlite数据库加密

Sqlite的数据库加密也很简单,我这里使用Sqlite Developer打开已有数据库,然后在数据库右键上选择Set Encryption Key,在弹出的对话框中输入密码即可。

我曾经专门针对Sqlite数据库机密机制做了一些了解,好像强度还是不错,而且据说性能损失是很少的。我在开发测试的时候,性能方面确实看不出太大的干扰。

面向对象的三大特征:封装、继承、多态

3、连接字符串增加加密内容

由于我们希望数据库配置项尽可能简洁,因此可以不用在配置文件中指定访问密码,这样也避免了加密字符串的泄密问题,我们可以通过动态设置数据库访问对象Database 的数据库访问密码属性进行内存上处理。如下代码所示是对Access数据库连接字符串进行增加加密字符串的操作。

        #region 连接字符串加密
面向对象的三大特征:封装、继承、多态
        /// <summary>
        /// 根据配置数据库配置名称生成Database对象
        /// </summary>
        /// <returns></returns>
        protected virtual Database CreateDatabase()
        {
            Database db = null;
            if (string.IsNullOrEmpty(dbConfigName))
            {
                db = DatabaseFactory.CreateDatabase();
            }
            else
            {
                db = DatabaseFactory.CreateDatabase(dbConfigName);
            }

            DbConnectionStringBuilder sb = db.DbProviderFactory.CreateConnectionStringBuilder();
            sb.ConnectionString = GetConnectionString();
            GenericDatabase newDb = new GenericDatabase(sb.ToString(), db.DbProviderFactory);
            db = newDb;

            return db;
        }

        /// <summary>
        /// 动态改变或者连接字符串
        /// </summary>
        /// <returns></returns>
        protected virtual string GetConnectionString()
        {
            string connectionString = "";
            DatabaseSettings setting = ConfigurationManager.GetSection("dataConfiguration") as DatabaseSettings;
            if(setting != null)
            {
                string defaultConnection = setting.DefaultDatabase;
                connectionString = ConfigurationManager.ConnectionStrings[defaultConnection].ConnectionString;

                //尝试加密或者解密
                if(!connectionString.EndsWith(";"))
                {
                    connectionString += ";";
                }
                connectionString += string.Format("Jet OLEDB:Database Password=testpassword;");
            }

            return connectionString;
        }

        #endregion
面向对象的三大特征:封装、继承、多态

通过在访问数据库的时候,动态增加加密的连接字符串,在系统的配置文件上,就和普通的没什么差别了,如下所示

面向对象的三大特征:封装、继承、多态
  <connectionStrings>
    <!--路径符号|DataDirectory|代表当前运行目录-->
<add name="Access" providerName="System.Data.OleDb"
         connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database1.accdb;User ID=Admin;"/>
    <add name="sqlite" providerName="System.Data.SQLite" connectionString="Data Source=|DataDirectory|\ForumMis.db;Version=3;"/>

  </connectionStrings>
面向对象的三大特征:封装、继承、多态

上面配置文件,Access数据库用的是2007格式的,所以用了Provider=Microsoft.ACE.OLEDB.12.0,如果是Access2000的话,那么就是Provider=Microsoft.Jet.OLEDB.4.0(基于安全原因,不用)。

Sqlite数据库的操作也类似, 它的加密字符串例子如下:Data Source=c:\mydb.db;Version=3;Password=myPassword;。

通过动态在连接字符串中增加加密字符串的方式,对于这些部署到客户端的数据库,第一个是提高安全性,用户分析不到那种加密类型;第二个是用户连接字符串不受干扰,可以正常阅读;第三是不用引入更多的模块和代码去实现。

以上只是我Winform开发框架用到的数据库字机密机制的一种,供大家参考和指正。

 

面向对象的三大特征:封装、继承、多态主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架、WCF开发框架的研究及应用。
  转载请注明出处:
面向对象的三大特征:封装、继承、多态撰写人:伍华聪   http://www.iqidi.com 
    
 
 

CYQ.Data 快速开发之UI(赋值、取值、绑定)原理

昨夜园子猴子问了几个我CYQ.Data使用的小问题,经过简单解答后,他表示“妈妈再也不用担心我的学习",并于事后以资鼓励,希望这框架越走越好

除了技术上的交流,双方在生活,S上面的问题上也进行了双边友好交流,最后猴子给发了一个国外的Sex网站,对此分享行为,我表示高度赞赏。

 

好了,言归正题,讲点技术问题:

CYQ.Data 的使用操作方式,已经有相关文章介绍了,就不再介绍了。
本节就讲一下实现原理,具体源码,可直接下载开源的V4.0可以学习。
下载地址: http://www.cyqdata.com/download/article-detail-426

 

 

CYQ.Data 支持的UI:WebForm和Winform 及实现原理:

 

涉及的内部2个类和一个接口:

面向对象的三大特征:封装、继承、多态 

 

MActionUI:

主要是对单行数据的操作,将单行的数据赋值到WebForm的服务器控件或Winform的控件。

面向对象的三大特征:封装、继承、多态 

其功能就是对UI控件单个取值和赋值,而新增的SetAll,可以批量把值赋值控件。

示例代码:

面向对象的三大特征:封装、继承、多态
             using (MAction action =  new MAction( " Users "))
            {
                 if (action.Fill(id))
                {
                    action.SetToAll( this);
                }
            }
面向对象的三大特征:封装、继承、多态

 

就这么一行SetToAll(this),就秒杀了以前的N多的类似以下的代码:

txtID.Text = XXX.值1;
txtUserName.Text = XXX.值2;
txtFullName.Text = XXX.值3;
txtEmailName.Text = XXX.值4;
txtPassword.Text = XXX.值5;
....省略N个..... 

 

而且带来的好处是,就算添加或减少字段显示项,只要把页面的控件去掉即可,并不即改动代码。

 

那这个功能实现原理是什么?

其实就是“this",等于传进了当前Page,然后只要遍历Page的子控件,根据约定的“三个字母前缀”+字段名,就可以循环设置值了。

 

MBindUI:

主要是对多数据的操作,将多行的数据绑定到WebForm或Winform的GridView,Repleater,DropDownList等列表控件。

面向对象的三大特征:封装、继承、多态 

其功能其实很简单,就是绑定列表控件,看以下以下代码,大致就能理解了:

面向对象的三大特征:封装、继承、多态
   public  static  void Bind( object ct,  object source)
        {
             if (ct  is GridView)
            {
                ((GridView)ct).DataSource = source;
                ((GridView)ct).DataBind();
            }
             else  if (ct  is Repeater)
            {
                ((Repeater)ct).DataSource = source;
                ((Repeater)ct).DataBind();
            }
             else  if (ct  is DataList)
            {
                ((DataList)ct).DataSource = source;
                ((DataList)ct).DataBind();
            }
             else  if (ct  is DataGrid)
            {
                ((DataGrid)ct).DataSource = source;
                ((DataGrid)ct).DataBind();
            }
             else  if (ct  is Win.DataGrid)
            {
                ((DataGrid)ct).DataSource = source;
            }
             else  if (ct  is Win.DataGridView)
            {
                ((System.Windows.Forms.DataGridView)ct).DataSource = source;
            }
             else  if (ct  is BaseDataList) // 基类处理
            {
                ((BaseDataList)ct).DataSource = source;
                ((BaseDataList)ct).DataBind();
            }
        }
面向对象的三大特征:封装、继承、多态

 

通过多个分支,设置数据源的值,而经典的使用方式就是:

             using (MAction action =  new MAction( " Users "))
            {
                action.Select().Bind(gvUsers);
            } 

 

当然,这并不是最佳性能的使用方式,因为列表控件的绑定,最好是在数据库链接关闭后再绑定,最佳性能写法应该下:

            MDataTable dt;
             using (MAction action =  new MAction( " Users "))
            {
                dt = action.Select();
            }
            dt.Bind(gvUsers); 

 

IUIValue:

这是一个支持自定义控件或第三方控件的接口,只要控件实现接口,也可以使用MActionUI的功能。

面向对象的三大特征:封装、继承、多态

三个属性,控件是否启,控件ID,控件的值,这个一般只有自己编写的自定义控件才会使用到。

 

UI这一块差不多就讲到这里了,实现还算简单,但思路却是多年经验步步优化累积而来。

 

传统非UI开发模式: 

 

除开WebForm,事实还有很多种开发模式,但万变不离其宗的是,本质是html元素通过GET、POST等方式提交与服务端交互。
而这种交互中间,最常见的就是js,而交互的格式,json是深受喜爱的。

 

 

所以CYQ.Data 也考虑到这种开发模式的快速开发方式,通过GetFromJson与ToJson功能,实现简单后端编码:

示例代码如:

面向对象的三大特征:封装、继承、多态
             string result;
             using (MAction action =  new MAction( " Users "))
            {
                 if (action.Fill(id))
                {
                    result=action.Data.ToJson();
                }
            }
            Response.Write(result); 
面向对象的三大特征:封装、继承、多态

通过返回Json到客户端,由客户端js解析并显示。

 

同样的返过来批量取值:

面向对象的三大特征:封装、继承、多态
             bool result;
             using (MAction action =  new MAction( " Users "))
            {
                action.GetFromJson(Request[ " json "]);
                result = action.Insert();
            }
            Response.Write(result); 
面向对象的三大特征:封装、继承、多态

由客户端js提交json格式的数据,而后台固定自动解析,入库,相当方便。

 

OK,本节就介绍到这里,谢谢观赏。