请问有人能给我解释一下抽象类、接口和混合类之间的区别吗?我以前在代码中使用过每种方式,但我不知道它们之间的技术差异。
请问有人能给我解释一下抽象类、接口和混合类之间的区别吗?我以前在代码中使用过每种方式,但我不知道它们之间的技术差异。
抽象类是一种不能被实例化的类。抽象类可以没有实现、部分实现或全部实现。抽象类旨在允许其子类共享一个通用(默认)实现。一个(伪代码)抽象类的例子可能如下所示:
abstract class Shape {
def abstract area(); // abstract (unimplemented method)
def outline_width() = { return 1; } // default implementation
}
class Rectangle extends Shape {
int height = width = 5;
def override area() = { return height * width; } // implements abstract method
// no need to override outline_width(), but may do so if needed
}
def main() = {
Shape[] shapes = { new Rectangle(), new Oval() };
foreach (s in shapes) {
print("area: " + s.area() + ", outline width: " + s.outline_width());
}
}
interface Shape {
def area(); // implicitly abstract so no need for abstract keyword
def outline_width(); // cannot implement any methods
}
class Rectangle implements Shape {
int height = width = 5;
def override area() = { return height * width; }
def override outline_width() = { return 1; } // every method in interface must be implemented
}
def main() = {
Shape[] shapes = { new Rectangle(), new Oval() };
foreach (s in shapes) {
print("area: " + s.area() + ", outline width: " + s.outline_width());
}
}
interface
一词,指的是Java和C#关键字。 Mixins不是接口。它们是多重继承。只是名字更好听了。
这并不是说mixins不好。多重继承并不坏。 C++解析多重继承的方式是让每个人都感到不安。
接下来是老掉牙的Shape示例
mixin Shape {
def abstract area();
def outline_width() = { return 1; }
}
class Rectangle with Shape {
int height = width = 5;
def override area() = { return height * width; }
}
def main() = {
Shape[] shapes = { new Rectangle(), new Oval() };
foreach (s in shapes) {
print("area: " + s.area() + ", outline width: " + s.outline_width());
}
}
interface Shape
{
int Area();
}
static class ShapeExtensions
{
public static int OutlineWidth(this Shape s)
{
return 1;
}
}
class Rectangle : Shape
{
int height = 5;
int width = 5;
public int Area()
{
return height * width;
}
}
class Program
{
static void Main()
{
Shape[] shapes = new Shape[]{ new Rectangle(), new Oval() };
foreach (var s in shapes)
{
Console.Write("area: " + s.Area() + ", outline width: " + s.OutlineWidth());
}
}
}
一般来说:
接口是指定操作但没有任何实现的契约。一些语言(如Java、C#)内置了对接口的支持,而在其他语言中,“接口”描述了类似于C++中的纯虚类的约定。
抽象类是指定至少一个没有实现的操作的类。抽象类还可以提供它们实现的某些部分。同样,有些语言内置了将类标记为抽象的支持,而在其他语言中它是隐含的。例如,在C++中,定义了纯虚方法的类是抽象的。
混合类是一种设计用于使子类中某些功能的实现更容易的类,但不是设计用于单独使用的。例如,假设我们有一个处理请求对象的接口。
interface RequestHandler {
void handleRequest(Request request);
}
也许将请求缓冲起来,累积它们直到达到某个预定数量再刷新缓冲区是有用的。我们可以通过使用mixin实现缓冲功能,而不必指定刷新行为:
abstract class BufferedRequestHandlerMixin implements RequestHandler {
List<Request> buffer = new List<Request>();
void handleRequest(Request request) {
buffer.add(request);
if (buffer.size == BUFFER_FLUSH_SIZE) {
flushBuffer(buffer);
buffer.clear();
}
}
abstract void flushBuffer(List<Request> buffer);
}
这种方式使我们能够轻松编写一个请求处理程序,将请求写入磁盘、调用Web服务等,而无需每次重写缓冲功能。 这些请求处理程序可以简单地扩展BufferedRequestHandlerMixin
并实现flushBuffer
。
另一个很好的混合类示例是Spring中的许多支持类之一,即HibernateDaoSupport。
由于很多人已经解释了定义和用法,我只想强调几个重要点。
接口:
抽象类:
在几个密切相关的类之间共享代码。它建立了“是一个”关系。
在相关类之间共享公共状态(状态可以在具体类中修改)
我将通过一个小例子来解释它们之间的区别。
Animal
可以是一个抽象类。Cat
和 Dog
扩展这个抽象类建立了“是一个”关系。
Cat 是 Animal
Dog 是 Animal.
Dog 可以
实现 Bark
接口。然后 Dog 具有 Bark 的能力。
Cat 可以
实现 Hunt
接口。然后 Cat 具有 Hunting 的能力。
Man,不是 Animal,可以实现 Hunt
接口。然后 Man 具有 Hunting 的能力。
Man 和 Animal(Cat/Dog)没有关联。但是 Hunt 接口可以为不相关的实体提供相同的能力。
Mixin:
如果我想声明一个抽象类,我将遵循以下两种方法之一。
Move all abstract methods to interface
and my abstract class implements that interface.
interface IHunt{
public void doHunting();
}
abstract class Animal implements IHunt{
}
class Cat extends Animal{
public void doHunting(){}
}
相关的SE问题:
抽象类基本上就是带有一些具体实现的接口。而接口只是指定了一份没有实现细节的契约。
如果您想要在实现抽象类的所有对象之间创建共同功能,则可以使用抽象类。这符合面向对象编程中DRY(不要重复自己)原则。
抽象类是一种类,其中并非所有成员都被实现,而是留给继承者来实现。它强制其继承者实现其抽象成员。 抽象类不能被实例化,因此它们的构造函数不应该是公共的。
以下是C#中的一个示例:
public abstract class Employee
{
protected Employee(){}
public abstract double CalculateSalary(WorkingInfo workingInfo);//no implementation each type of employee should define its salary calculation method.
}
public class PartTimeEmployee:Employee
{
private double _workingRate;
public Employee(double workingRate)
{
_workingRate=workingRate;
}
public override double CalculateSalary(WorkingInfo workingInfo)
{
return workingInfo.Hours*_workingRate;
}
}
接口是一个类要实现的契约。它只声明了实现类成员的签名,本身没有实现。我们通常使用接口来实现多态,并解耦相关的类。
以下是C#中的一个示例:
public interface IShape
{
int X{get;}
int Y{get;}
void Draw();
}
public class Circle:IShape
{
public int X{get;set;}
public int Y{get;set;}
public void Draw()
{
//Draw a circle
}
}
public class Rectangle:IShape
{
public int X{get;set;}
public int Y{get;set;}
public void Draw()
{
//Draw a rectangle
}
}