`
Flory
  • 浏览: 24701 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

探讨继承与实现

 
阅读更多

继承是建立一个类,然后创建它的更特殊的版本。是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 成员引用的实际地址。

分享到:
评论

相关推荐

    c语言实现继承与多态

    【C语言实现继承与多态】的探讨主要集中在如何在非面向对象的语言——C语言中,利用其特性模拟实现面向对象编程的关键概念:封装、继承和多态。 封装是面向对象设计的基础,它通过将数据和操作数据的函数捆绑在一起...

    java script 继承的实现

    本文将深入探讨 JavaScript 中的继承实现方式,并结合提供的 "zinherit.js" 文件来解析相关知识点。 在 JavaScript 中,继承主要通过原型链(prototype chain)、构造函数继承、组合继承、原型式继承、寄生式继承、...

    类的继承的简单实现

    在"类的继承的简单实现"这个主题中,我们将探讨如何在不同的编程语言中实现类的继承,以及它带来的优势和应用场景。下面我们将深入讲解以下几个方面: 1. **类的继承定义**:继承允许子类(也称为派生类)获取父类...

    java 实现接口和继承关系

    在Java编程语言中,接口的实现与类的继承是两个非常重要的概念,它们共同构成了面向对象编程中的多态性基础。下面将详细解释这两个概念及其应用场景,并探讨它们之间的区别。 ### 接口的实现 #### 定义 接口...

    C++类的继承与实现

    首先,让我们详细探讨一下C++中的类继承。继承是面向对象编程中的一个概念,它允许创建一个新的类(子类或派生类)基于已存在的类(父类或基类)。通过继承,子类可以自动获得父类的所有公共属性和方法,同时还可以...

    JS继承的实现方式

    下面将详细介绍几种常见的继承实现方式,并探讨它们的特点与应用场景。 #### 一、原型链继承 **核心思想**: 将父类的实例设置为子类的原型。 **实现方式**: ```javascript function Animal(name) { this.name = ...

    详解Javascript继承的实现

    总结来说,JavaScript提供了多种继承实现方式,每种都有其优缺点。在选择继承策略时,应考虑代码的可读性、性能和兼容性等因素。随着语言的发展,新的语法特性(如ES6的`class`)和库的出现,使得JavaScript的继承...

    c++程序设计 继承与派生实验(二)

    在这个“C++程序设计 继承与派生实验(二)”中,我们将深入探讨这三个关键知识点:类的派生与继承的概念、继承方式对成员访问权限的影响,以及虚基类的用法。 首先,让我们理解类的继承与派生。继承是面向对象设计...

    JavaScript继承机制探讨及其应用.pdf

    JavaScript继承机制探讨及其应用 JavaScript是一门弱类型语言,具有函数式编程和面向对象编程的特点。随着近几年JavaScript生态圈的发展和成熟,项目的编码量和复杂度也在呈几何级数增长。JavaScript面向对象编程中...

    实现继承与派生

    在这个主题中,我们将深入探讨如何通过继承和派生来实现函数的多态性,并理解同名覆盖的概念。 继承是面向对象编程中的一个关键特性,它允许一个类(称为子类或派生类)获取另一个类(称为父类或基类)的属性和方法...

    继承实现顺序栈学习代码示例

    在这个“继承实现顺序栈”的示例中,我们将深入探讨如何使用面向对象编程中的继承概念来创建一个顺序栈。顺序栈是栈的一种实现方式,它使用数组作为底层数据结构。 首先,我们要理解什么是继承。继承是面向对象编程...

    采用普通类,接口,和抽象类实现单继承和多继承增,删,改,查

    本主题将深入探讨如何使用普通类、接口和抽象类来实现这些继承方式,并应用到“增、删、改、查”(CRUD,Create, Read, Update, Delete)操作中。 首先,单继承是指一个子类只能继承一个父类的特性。这种方式使得...

    JavaScript实现继承的几种方式

    本篇文章将深入探讨JavaScript中实现继承的几种常见方式。 1. 原型链继承 JavaScript的原型(prototype)机制是实现继承的基础。每个函数都有一个prototype属性,这个属性指向一个对象,这个对象的属性和方法可以被...

    JS继承.txtJS继承.txt

    接下来,我们将详细探讨这些继承方式。 ### 1. 原型链继承 原型链继承是通过将一个对象设置为另一个对象的原型,从而实现继承的一种方法。这种方式简单直观,但存在一些缺点,比如不能向父类传递初始化参数,且...

    js 实现类式继承

    在JavaScript中,实现类式继承是面向对象编程中的一...同时,通过创建模型类,我们可以组织数据并实现与服务器的通信,确保数据的同步和更新。这些知识对于理解JavaScript的面向对象编程和复杂应用程序的设计至关重要。

    C++继承与派生机制详解

    本文档由一位资深软件公司的讲师编写,深入探讨了C++中继承与派生的具体机制。 #### 二、派生类的基本声明 在C++中,派生类的声明格式通常如下所示: ```cpp class Derived : access_specifier Base { // 新增成员...

    深入探索JavaScript的原型继承:机制、实现与最佳实践

    本文将深入探讨JavaScript原型继承的工作原理、实现方式以及在现代Web开发中的应用。 JavaScript的原型继承是一种强大且灵活的机制,它允许对象之间共享功能和行为。通过深入理解原型继承的工作原理和实现方式,...

    继承与多态程序演示

    在这个"继承与多态程序演示"中,我们将深入探讨这两个概念,以及如何在Microsoft Foundation Classes (MFC) 框架下实现它们。 首先,让我们了解什么是继承。继承是一种设计模式,允许一个类(子类或派生类)从另一...

Global site tag (gtag.js) - Google Analytics