在实际项目中,当我们设计一个父类时,经常会遇到这个类不能确定它的具体执行流程的。比如我设计一个文件类:
public class AFile
{
private string name = string.Empty;
private string path = string.Empty;
private FileType type = FileType.IsUnknown;
public string Name
{
get
{
return name;
}
}
public string Path
{
get
{
return path;
}
}
public FileType Type
{
get { return type; }
}
public AFile(string name, string path, FileType type)
{
this.name = name;
this.path = path;
this.type = type;
}
public void Copy(string destPath)
{
//不知道怎么写,因为可能是文件还可能是文件夹,如果是压缩的还要解压
}
}
public enum FileType
{
IsUnknown = 0,//类型不明
IsFile = 1,//文件
IsDirectory =2,//文件夹
IsCompression//压缩的
}
这是一个父类,它的copy方法,应该怎么写呢?因为文件存在四种状态甚至后来根据需要还可能再加,针对不同的文件类型,拷贝方法是不一样的,而且根据项目需要还可能针对某种文件做一些特殊处理。这样再设计这个父类时就不能对copy方法写代码,只需要谁继承它谁就重写这个方法,根据需要写不同的执行代码。
这样,一个类具有某个方法,但是该方法没有具体执行过程,这样的方法称之为“抽象方法”。
上面的AFile类中Copy方法就叫抽象方法,但是随之有一个问题,如果实例化了这个AFile类,Copy方法也就是这个对象的行为了,但实际上Copy方法还不确定。这样不符合客观事物规律。因此,这个类是不能被实例化的,也就是说当类中有抽象方法时,这个类不能被实例化,这样的类称之为“抽象类”。抽象不能被实例化,但它还是类。抽象类和抽象方法用abstract关键字修饰。
可以看到,抽象类中就存在了两种方法:抽象方法和非抽象方法。
非抽象方法,抽象类被继承,子类拥有非抽象方法,可以直接使用,也可以重写覆盖。
抽象类,必须覆盖重写。
修改上述的文件类:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace YYS.CSharpStudy.MainConsole
{
public abstract class AFile
{
private string name = string.Empty;
private string path = string.Empty;
private FileType type = FileType.IsUnknown;
public string Name
{
get
{
return name;
}
}
public string AFilePath
{
get
{
return path;
}
}
public FileType Type
{
get { return type; }
}
public AFile(string name, string path, FileType type)
{
this.name = name;
this.path = path;
this.type = type;
}
public abstract void Copy(string destPath);
}
public enum FileType
{
IsUnknown = 0,//类型不明
IsFile = 1,//文件
IsDirectory =2,//文件夹
IsCompression//压缩的
}
/// <summary>
/// 文件类
/// </summary>
public class FileInfo : AFile
{
public FileInfo(string name, string path, FileType type)
: base(name, path, type)
{
}
/// <summary>
/// 文件的拷贝方法
/// </summary>
public override void Copy(string destPath)
{
if (string.IsNullOrEmpty(destPath))
{
string sourcePath = this.AFilePath + this.Name;
//此时name是文件名,带有后缀名,加起来是文件路径
destPath += this.Name;
if (File.Exists(sourcePath))
{
File.Copy(sourcePath, destPath, true);
}
}
}
}
/// <summary>
/// 文件夹类
/// </summary>
public class FileDirectoryInfo : AFile
{
public FileDirectoryInfo(string name, string path, FileType type)
: base(name, path, type)
{
}
/// <summary>
/// 文件的拷贝方法
/// </summary>
public override void Copy(string destPath)
{
if (string.IsNullOrEmpty(destPath))
{
string sourcePath = this.AFilePath + this.Name;
//此时文件名是文件夹名,加起来是文件夹路径
destPath += this.Name;
if (Directory.Exists(sourcePath))
{
CopyDirectory(sourcePath, destPath);
}
}
}
/// <summary>
/// 拷贝文件夹的方法
/// </summary>
private void CopyDirectory(string sourcePath, string destPath)
{
try
{
if (!Directory.Exists(destPath))
{
Directory.CreateDirectory(destPath);
}
DirectoryInfo directoryInfo = new DirectoryInfo(sourcePath);
foreach (FileSystemInfo fileInfo in directoryInfo.GetFileSystemInfos())
{
string subFileOrDirectoryName = Path.Combine(destPath, fileInfo.Name);
if (fileInfo is DirectoryInfo)
{
this.CopyDirectory(fileInfo.FullName, subFileOrDirectoryName);
}
else
{
if (File.Exists(sourcePath))
{
File.Copy(sourcePath, destPath, true);
}
}
}
}
catch{}
}
}
}
这样,就完成了抽象类的继承并实现。但是如果子类继承了抽象类,但是并没有实现抽象方法,那么这个子类也将作为一个抽象类存在。有抽象方法的类叫做抽象类,对于有些情况,没有抽象方法的类,也可以使用abstract关键字定义为抽象类,这样表明该类不能被抽象,必须被继承。