探讨继承与实现

继承是建立一个类,然后创建它的更特殊的版本。是OOP中不可缺少的部分。
人在描述事物的时候是有层次的,那么继承就使程序对现实世界有层次的描述的表达成为可能。对程序员来说继承的重点是共同点。因为有共同点才能重用。

实现是建立一个接口,然后由某些类来实现接口描述的细节。就好比是工程师绘制了部件,然后由工人做出具体的产品,工程师并没有去制造部件。

类与接口的区别就在于此,类不但有描绘,还实现了部分细节。而特殊的抽象类完全带抽象方法,就和接口完成的同样功用。而且,无论接口还是类,都不是凭空去描绘出来的 ,否则就是纸上谈兵了,而是根据具体类的特征抽象出来的。所以他们有共同点。

目录
一、继承与实现
接口实现示例
类继承示例
二、继承,实现简单论述
1、接口的实现以及接口对类的访问
2、类的继承关于以及父类对子类的访问

一、继承与实现
抽象有两种抽象方式。
1、他们有相同的工作方式;
2、他们有相同的名称、作用和特征。
第一种方式是类的继承,而第二种方式是接口的实现。

比如:数据库操作中一般都会用到 添加,删除,更新,读取。那么就是他们都有相同的名称、作用和特征。就可以使用接口实现。

using System.Collections;
using System.Data;

interface IMyData
{
void MyInsert(ArrayList al);
void MyDelete(ArrayList al);
void MyUpdate(ArrayList al);
DataSet MySelect(ArrayList al);
}
using System;

namespace FmRadio
{
/** <summary>
/// DMusicSort 的摘要说明。
/// </summary>
public class DMusicSort : IMyData
{
public DMusicSort()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
IMyData 成员#region IMyData 成员

public void MyInsert(System.Collections.ArrayList al)
{
// TODO: 添加 DMusicSort.MyInsert 实现
}

public void MyDelete(System.Collections.ArrayList al)
{
// TODO: 添加 DMusicSort.MyDelete 实现
}

public void MyUpdate(System.Collections.ArrayList al)
{
// TODO: 添加 DMusicSort.MyUpdate 实现
}

public System.Data.DataSet MySelect(System.Collections.ArrayList al)
{
// TODO: 添加 DMusicSort.MySelect 实现
return null;
}

#endregion
}
}
再比如:数据库的连接,这里只说MS Sql Srever 2000,在一个程序只使用一个库的情况下,所有关于数据库操作类都将执行相同的数据库连接。他们有相同的工作方式。

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace FmRadio
{
/** <summary>
/// MyConnection 的摘要说明。
/// </summary>
public class MyConnection
{
private SqlConnection pConn;

public MyConnection()
{
//
// TODO: 在此处添加构造函数逻辑
//
pConn = new SqlConnection(ConfigurationSettings.AppSettings["DbLink"]);
}

public SqlConnection conn
{
get
{
// TODO: 添加 MyConnection.conn getter 实现
return pConn;
}
}
}
}
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

namespace FmRadio
{
/** <summary>
/// Execute 的摘要说明。
/// </summary>
public class Execute : MyConnection
{
private int sType = 0;
private ArrayList pPara;
private string pContext;

public Execute()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

public Execute(string pContext,ArrayList pPara)
{
this.pPara = pPara;
this.pContext = pContext;
}

public Execute(int pType,string pContext,ArrayList pPara)
{
this.sType = pType;
this.pPara = pPara;
this.pContext = pContext;
}

public int ExeNone()
{
// TODO: 添加 Execute.ExeNone 实现
SqlCommand sc = null;
CommandType ct = CommandType.StoredProcedure;
if(this.sType==0)
ct = CommandType.StoredProcedure;
else
ct = CommandType.Text;

int rs = 0;
sc = new SqlCommand();
sc.CommandType = ct;
sc.Connection = conn;
sc.CommandText = pContext;
foreach(DataPara dp in pPara)
{
sc.Parameters.Add("@" + dp.ColName,dp.ColContent.GetType()).Value = dp.ColContent;
}
// try
// {
conn.Open();
rs = sc.ExecuteNonQuery();
conn.Close();
// }
// catch{}
return rs;
}

public DataSet ExeTable()
{
// TODO: 添加 Execute.ExeTable 实现
SqlDataAdapter sda = new SqlDataAdapter();
SqlCommand sc = null;
CommandType ct = CommandType.StoredProcedure;
if(this.sType==0)
ct = CommandType.StoredProcedure;
else
ct = CommandType.Text;

sc = new SqlCommand();
sc.CommandType = ct;
sc.Connection = conn;
sc.CommandText = pContext;
foreach(DataPara dp in pPara)
{
sc.Parameters.Add("@" + dp.ColName,dp.ColContent.GetType()).Value = dp.ColContent;

 

}
sda.SelectCommand = sc;
DataSet ds = new DataSet();
// try
// {
conn.Open();
sda.Fill(ds,"asdasd");
conn.Close();
// }
// catch{}
return ds;
}

}
}

二、继承,实现简单论述
下面,我们找更加简单的例子来探讨继承和实现。

1、接口的实现以及接口对类的访问
interface A
{
void a();
}
using System;

namespace Mocl
{
/** <summary>
/// A的摘要说明。
/// </summary>
public class A : IA
{
public A()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
IA 成员#region IA 成员

public void a()
{
// TODO: 添加 A.a 实现
System.Diagnostics.Debug.WriteLine("a");
}

#endregion

public void b()
{
System.Diagnostics.Debug.WriteLine("b");
}
}
}
执行以下方法
using System;

namespace Mocl
{
/** <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/** <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序

A a = new A();
a.a();
a.b();
IA c = new A();
c.a();
}
}
}


输出
a
b
a

IA c = new A();通过接口访问类。注意使用IA c = new A();的时候,对象c是访问不到类A的方法成员void b()的。因为父类访问子类的时候只会返回父类所定义的方法成员的引用。

我们可以再给类A 添加个字段 public int i = 0;
A的方法a换成
public void a()
{
// TODO: 添加 A.a 实现
System.Diagnostics.Debug.WriteLine("a" + i.ToString());
}

继续执行,发现输出
a0
b
a0
从这点上看出接口对子类的引用并不阻止类执行在访问过程中要使用到的成员,无论这些成员是否是接口的一部分。

2、类的继承关于以及父类对子类的访问
我是在网上看了类似的问题,才有兴趣对继承的各种关系进行学习。才有此文,和大家分享我的学习体会。所以这里就用他的原问题,进行探讨。



public class A
{
public void printA()
{
System.Diagnostics.Debug.WriteLine("printA");
}
public virtual void valueA()
{
System.Diagnostics.Debug.WriteLine("ValueA");
}
}

public class B:A
{
new public void printA()
{
System.Diagnostics.Debug.WriteLine("printB");
}

public override void valueA()
{
System.Diagnostics.Debug.WriteLine("ValueB()");
}
}

using System;

namespace Mocl
{
/** <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/** <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
B BTemp=new B();
A ATemp=BTemp;
ATemp.printA();
ATemp.valueA();
BTemp.printA();
BTemp.valueA();
}
}
}

输出:
printA
ValueB()
printB
ValueB()

直接对B的访问B BTemp=new B(); 肯定都能理解。但是A对B的访问 A ATemp=BTemp; (与 A ATemp= new B(); 相当)为什么会得到这样的输出呢?

在讨论问题之前,先来看两个关键字virtual 和new
1、new 的意义
new是在程序编译过程中指定方法引用新的指向地址。
2、virtual 的意义
virtual是在程序运行时确定方法引用的地址。

问题1:类B的方法
new public void printA()
{
System.Diagnostics.Debug.WriteLine("printB");
}
不是覆盖了类A的
public void printA()
{
System.Diagnostics.Debug.WriteLine("printA");
}
了吗?怎么还会输出printA呢?

那是因为new方法只在本类被实例化时才会覆盖父类的方法,它并不直接覆盖父类的方法。
而A ATemp= new B(); 由于类A在编译的时候已经确定了它的结构,除了标明virtual 的成员都已经被固定,而virtual 成员的引用地址是动态执行的。程序运行时,在父类访问子类的时候,需要把子类转换成父类,而子类对virtual 的覆盖将告诉父类的virtual 成员引用的实际地址。new 关键字是不起作用的。new是在编译的时候确定的新引用地址,不会对父类产生影响。

问题2:类B的
public override void valueA()
{
System.Diagnostics.Debug.WriteLine("ValueB()");
}
方法为什么覆盖了父类的
public virtual void valueA()
{
System.Diagnostics.Debug.WriteLine("ValueA");
}
方法。

答案就是上面的
程序运行时,在父类访问子类的时候,需要把子类转换成父类,而子类对virtual 的覆盖将告诉父类的virtual 成员引用的实际地址。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值