Inheritance 开闭原理与继承的区别

Inheritance 开闭原理与继承的区别,inheritance,polymorphism,abstraction,solid-principles,open-closed-principle,Inheritance,Polymorphism,Abstraction,Solid Principles,Open Closed Principle,我知道开闭原理是指为扩展而开,为修改而关。考虑下面的例子: public class Vehicle{ public void service(){ //vehicle servicing code } } public class Bike extends Vehicle{ public void service(){ // bike specific servicing } } 现在我了解到,Bike类扩展了Vehicl

我知道开闭原理是指为扩展而开,为修改而关。考虑下面的例子:

public class Vehicle{
    public void service(){
        //vehicle servicing code
    }
}

public class Bike extends Vehicle{

    public void service(){
        // bike specific servicing 
    }
}
现在我了解到,
Bike
类扩展了
Vehicle
,并使用开闭原理添加了新功能


考虑我创建
Vehicle
类的jar文件,然后
Bike
类从jar扩展
Vehicle
类。在这种情况下,我们不能修改
Vehicle
类和
Bike
扩展它。这是开闭原理的一个好例子吗?
我想知道OCP与继承有何不同

OCP与继承没有什么不同,相反,OCP的“打开”部分是开放的,可以扩展,但应该关闭以进行修改。 也就是说,代码应该只针对错误/bug进行修改,但对于新的扩展或功能的更改,应该对其进行扩展


作为补充说明,我认为这最好放在programmers.stackexchange.com网站上。

以下是我对解释OCP的看法:

OCP指出,代码可以根据其更改的频率进行分类,“同一”代码的各个部分可以有不同的更改频率,我所说的更改不仅指随着时间的推移而更改,还指在运行时更改-例如,选择这段或那段特定的代码来执行某些操作

OCP要求将更稳定的代码与更可能更改的代码分开。但它并不止于此,它还要求更改频率较低的代码能够与更改频率较高的代码一起工作

那么OCP==继承呢?不,继承只是用于实现OCP的技术之一。策略模式、装饰模式、普通组合、参数多态性(又称泛型)和其他技术也可以用来实现这些目标

我所说的不同变化频率的例子。让我们设想一些集合实现。如果每次向语言中添加一些基元类型时,集合代码也需要更新,这不是很糟糕吗?因此,集合将其持有的项目视为不透明,从而实现OCP。下一个示例,让我们以上一个示例中相同的集合实现为例,设想我们要打印排序后的元素。简单。我们将只向集合中添加排序。。。。以及其他10种收集类型?而每一个新的集合也必须实现这种排序?可怕的。如果我们的排序算法只是将集合视为不透明类型,那么如果被要求,它会连续提供它的项,这不是更好吗?这是我们的排序需要集合做的唯一事情,一旦给出元素列表,它就可以进行实际的排序。好啊所以现在集合只需要支持一个连续返回所有项的操作。容易的。。。如果我们仔细想想,这是一个非常有用的行为,可以用于过滤、转换等

希望通过上面的例子,我展示了继承之外的一些OCP用法,并表明OCP还鼓励我们将代码视为不同抽象级别的组合(具有不同变化频率的代码组合)。

问题:没有继承 让我们根据问题中给定的代码构建一个示例。不同的车辆以不同的方式进行维修。因此,我们对
自行车
汽车
有不同的分类,因为维修
自行车
的策略与维修
汽车
的策略不同

车库
类接受各种车辆进行维修。遵守规范并查看
车库
类如何违反开闭原则:

class Bike {
    public void service() {
        System.out.println("Bike servicing strategy performed.");
    }
}

class Car {
    public void service() {
        System.out.println("Car servicing strategy performed.");
    }
}

class Garage {
    public void serviceBike(Bike bike) {
        bike.service();
    }

    public void serviceCar(Car car) {
        car.service();
    }
}
正如您可能已经注意到的,无论何时维修诸如
Truck
Bus
之类的新车,都需要修改
Garage
,以定义新方法
serviceTruck()
serviceBus()
。这意味着
车库
类必须了解所有可能的车辆,如
自行车
汽车
公共汽车
卡车
等等。因此,它违反了开闭原则,开放进行修改。此外,它还不能扩展,因为要扩展新功能,我们需要更改它


解决方案:使用继承 抽象

为了解决上述代码中的问题并满足开闭原则,我们需要抽象出每种车型维修策略的实施细节。这意味着我们需要对
Bike
Car
类进行抽象

多态性

我们还希望
车库
类能够接受多种形式的车辆,比如
公共汽车
卡车
等等,而不仅仅是
自行车
汽车
。这意味着我们需要多态性(多种形式)

继承

因此,为了满足开闭原则,最重要的机制是抽象和多态性。在Java、C等静态类型语言中,提供抽象和多态性的重要工具是继承

为了抽象各种类型车辆维修策略的实施细节,我们使用了一个名为
Vehicle
接口
,并有一个抽象方法
service()

对于
Garage
类接受多种形式的
Vehicle
,我们将其方法的签名更改为
service(Vehicle-Vehicle){}
,以接受接口
Vehicle
,而不是像
Bike
这样的实际实现,
Car
等。我们还从类中删除了多个方法,因为只有一个方法可以接受多种形式

interface Vehicle {
    void service();
}

class Bike implements Vehicle {
    @Override
    public void service() {
        System.out.println("Bike servicing strategy performed.");
    }
}

class Car implements Vehicle {
    @Override
    public void service() {
        System.out.println("Car servicing strategy performed.");
    }
}

class Garage {
    public void service(Vehicle vehicle) {
        vehicle.service();
    }
}
关闭以进行修改

正如您在上面的代码中所看到的,现在
Garage
类已关闭以进行修改,因为现在它确实关闭了