前言
以下我将通过一种全新的方式带你理解到底什么才是接口多态,很多人包括我在内刚学习这个东西的时候感觉无从下手,别人讲不明白,自己也搞不懂,只单纯的知道如何写接口,之后就再也没有用过。以下我将通过问题引入的方式来带你理解接口。首先你要知道一个概念的提出或者一个功能的引入一定是为了解决某个问题的。那么接口解决了什么问题,为什么它如此受推崇。以下我们先从生活中来理解它,逐步由现实到抽象。我希望以最为通俗的说法来进行解释。
从生活中看接口
这里我们以最常见的手机的充电接口为例,大家要知道这个接口不光能够充电,而且还能进行文件传输、网络共享、并且和耳机、U盘等设备都可以进行交互和通信,当然它的功能不仅限于我刚才说的这些,还有好多好多,并且我们也可以对其进行编程。它是如何实现的?这个东西其实蛮有意思的。
这个接口其实规定了一些数据传输的标准,那么什么又是数据传输标准呢?你首先要想:我们用这个接口干嘛?我们将刚才说的文件共享、耳机等所做的事情做进一步的概括那就是:与手机进行交流。那么什么是交流,我们从现实生活中理解的话就是人与人之间对话,对话需要什么?是不是需要语言?那么语言的本质是什么?是不是就是一个协定呀?也就是一个标准!如何理解?例如我给你说苹果
,你是不是会立马想到真实的苹果,那如果我说pomme
你能想到苹果吗?是不是不能,因为苹果
这个字是我们之间沟通/通信建立的一个标准,如果你想和我沟通就必须遵循这个标准,否则我们无法沟通,所以说接口建立的是一个数据传输的标准。当然我们可以借助一些适配器来完成接口的转换,例如刚才说的U盘想要插到手机上是不大可能的,所以就需要一个适配器,它所承担的就是一个翻译的工作。
以下我们以最为常见的数据访问接口举例说明。
常见的接口“数据访问层接口”
什么叫做“数据访问层接口”呢?这里我们先不直接来介绍,我们先来看一个例子。
我们首先有一个Student
类,再者有一个StudentService
的类,其中Student
类用于保存和传递数据,StudentService
类则提供两个方法第一个就是将Student
对象中的数据保存到SQLServer数据库中,第二个方法GetStudents
则是将SQLServer数据库中所有数据读取来并保存然后将数据返回。这里我们忽略具体代码,仅写出了大致步骤。
public class Student
{
public int StudentId{
get; set; }
public string StudentName{
get; set; }
public int Age {
get; set; }
}
public class StudentService
{
public int Add(Entities.Student student)
{
//拼接SQL语句
//创建SQLConnection对象并打开数据库链接
//创建CMD对象执行SQL语句
//接收并返回操作结果
return 1;
}
public List<Entities.Student> GetStudents()
{
//创建List对象集合
List<Entities.Student> students = new List<Entities.Student>();
//拼接SQL语句
//创建SQLConnection对象并打开数据库链接
//创建CMD对象执行SQL语句
//读取返回结果并保存到students对象中
//返回读取结果
return students;
}
}
接下来我们来模仿用户输入,将数据进行保存操作。以下我们创建了student对象,以及studentService对象,然后调用studentService的Add函数成功的将数据进行了保存。
static void Main(string[] args)
{
//1、获取用户输入数据(这里跳过获取)
int studentId = 1000;
string studentName = "QyLost";
int age = 18;
//2、创建Student对象的实例
Entities.Student student = new Entities.Student();
student.StudentId = studentId;
student.StudentName = studentName;
student.Age = age;
//3、创建StudentService对象实例
DAL.StudentService studentService = new DAL.StudentService();
//4、调用studentService对象的Add方法并接收结果
bool result = studentService.Add(student) == 1;
if (result)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Failed");
}
Console.ReadKey();
}
这样写起来貌似看着很是合理,但是你想一下,如果说我们需求发生了改变,由于某种原因(可能是客户原因或者技术原因)我们需要将数据库切换为json/xml文件保存。这下你能想到什么?改代码?没错你肯定先去改了代码,数据保存的地方变了,那么你肯定要去修改StudentService
中的两个函数了,于是就有了下边的代码。
其他地方没有改动,只是修改了Add和GetStudents函数中的所有代码,这样就完成了需求的变更。
public int Add(Entities.Student student)
{
//获取文件路径
//将对象转换位特定格式(json/xml/.....)
//创建文件流对象并打开操作流
//追加文件内容
//关闭文件流
return 1;
}
public List<Entities.Student> GetStudents()
{
//创建List对象集合
List<Entities.Student> students = new List<Entities.Student>();
//获取文件路径
//创建文件流对象并打开操作流
//解析文本数据(json/xml/.....)
//读取解析结果并保存到students对象中
//返回读取结果
return students;
}
需求总是变换莫测,随着时间的推移,突然那么一天又要将所有数据迁移到MySQL数据库,然后你默默的咬牙将StudentService
类中的两个方法进行了改动,出现了如下版本。
public int Add(Entities.Student student)
{
//拼接SQL语句
//创建MySQL数据链接对象并打开数据库链接
//创建MySQLCMD对象执行SQL语句
//接收并返回操作结果
return 1;
}
public List<Entities.Student> GetStudents()
{
//创建List对象集合
List<Entities.Student> students = new List<Entities.Student>