我在读这。上面写着
有些人认为,继承的目的是代码重用。在C++中,这是错误的。直截了当地说,“继承不是为了代码重用。”在C++中继承的目的是表达接口遵从性(子类型),而不是获得代码重用。在C++中,代码重用通常是通过组合而不是通过继承实现的。换句话说,继承主要是一种规范技术,而不是一种实现技术。
那么,我的问题是C++中的接口遵从性(子类型)到底是什么?如何使用继承来表示它?子类型和子类有何不同?如果有人给出合适的现实世界的例子来回答这个问题,那就更好了。
发布于 2015-08-29 18:55:02
与其拥有可重用的代码,不如使用可互换的代码。
使用DI和Adapter模式的实际示例。假设您有一个类,它处理数据。它不检索数据,而是处理数据。我们可以简单地称它为DataHandler。
class DataHandler
{
public:
void doSomethingWithData() {}
protected:
private:
};当您开始在应用程序中使用DataHandler时,可以使用它处理来自start的数据。因此,DataHandler将需要上述类的一个实例。
class SqlDatabaseDataRetriever
{
public:
Data getData() { }
protected:
private:
};
class DataHandler
{
public:
DataHandler(SqlDatabaseDataRetriever& dataRetriever)
{
_dataRetriever = dataRetriever;
}
void doSomethingWithData()
{
Data data = this->_dataRetriever.getData();
}
protected:
SqlDatabaseDataRetriever _dataRetriever;
private:
};但是,如果稍后您决定不希望通过SqlDatabaseDataRetriever直接访问数据库,那么您将创建一个API并创建新的类,该类用于通过API处理请求并从中检索数据。
因此,我们希望将DataHandler类与新的ApiDataRetriever一起使用,但目前我们的DataHandler使用的是不同的类。您可以重写代码,注入ApiDataRetriever,但是有一个更好的解决方案。
您将创建一个抽象类,所有的DataRetrievers都将继承它,然后注入这个抽象类并使用它的方法。
class DataRetriever
{
public:
virtual Data getData() = 0;
protected:
private;
}
class SqlDatabaseDataRetriever : public DataRetriever
{
public:
virtual Data getData() { }
protected:
private;
}
class ApiDataRetriever : public DataRetriever
{
public:
virtual Data getData() { }
protected:
private;
}
class DataHandler
{
public:
DataHandler(DataRetriever& dataRetriever)
{
_dataRetriever = dataRetriever;
}
void doSomethingWithData()
{
Data data = this->_dataRetriever.getData();
}
protected:
DataRetriever _dataRetriever;
private:
};由于父类中的函数被定义为纯虚拟函数,因此必须在子类中实现它,而且由于要注入父类,但不能实例化父类,因此始终会得到具有父方法的subject类,可以不受限制地使用该方法。
发布于 2015-08-29 20:20:37
子类型是满足基本类型契约的类型。
子类是从baseclass继承的类。
在C++ (不考虑模板)中,您只能通过子类创建子类型,这为编译器提供了许多用于优化和静态检查的附加信息。
对于objective,这个子类型只需要处理基本类型所理解的消息就不一样了:鸭型:“如果它看起来像鸭子,像鸭子一样游泳,那么它很可能就是鸭子。”
C++模板也是鸭式类型(类型必须有适当的成员),尽管完全是在编译时,因此不会受到任何动态类型的惩罚。
没有子类的子类型的一个例子是使用标准算法:
template<class T> void sortall(T& x) {
using std::begin;
using std::end;
std::sort(begin(v), end(v));
}它可以被调用,不管参数是std::vector、std::array还是其他容器,尽管这些示例中没有一个与继承相关。
虽然没有子类型的子类可以通过忽略继承的契约来实现,但这是一个罪过,我们应该避免犯这个错误。
https://softwareengineering.stackexchange.com/questions/294895
复制相似问题