当试图解释OOP中的继承概念时,常见的例子通常是哺乳动物。恕我直言,这确实是一个不好的例子,因为它将导致新手以错误的方式使用此概念。而且,他们在日常设计工作中将面临的不是常见的设计。
那么,使用继承解决的一个好,简单而具体的问题是什么?
当试图解释OOP中的继承概念时,常见的例子通常是哺乳动物。恕我直言,这确实是一个不好的例子,因为它将导致新手以错误的方式使用此概念。而且,他们在日常设计工作中将面临的不是常见的设计。
那么,使用继承解决的一个好,简单而具体的问题是什么?
Answers:
像哺乳动物这样的纯学术实例没有错。我也喜欢矩形/正方形示例,因为它指出了为什么现实世界中的分类法并不总是直接转换为您期望的继承关系。
我认为,最典型的日常示例是GUI工具包。这是每个人都在使用的东西,但是初学者可能没有对他们如何在后台工作进行推理。您可以谈论所有容器,所有小部件,事件等共有的行为,而无需了解任何给定实现的详细知识。
我的真实示例是一个简单的HR应用程序的域模型。我告诉我们可以创建一个名为Employee的基类,因为经理当然也是雇员。
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Code { get; set; }
public string GetInsuranceHistory()
{
// Retrieving insurance history based on employee code.
}
}
然后我解释说开发人员是员工,测试人员是员工,项目经理是员工。因此,他们都可以从员工类继承。
Employee
可能是一abstract
门课。
Developer
和a Tester
。另一个类似的情况是您拥有Customer
and 的联系人数据库Supplier
,但是正如创建了这样一个系统的任何人都会告诉您的那样,总是存在a Company
两者都是的情况。这就是为什么大多数这些示例都将您引向错误的方向。
封装变化的内容……向他们展示一个模板方法模式,它通过将常见行为放在基类中并将变化的行为封装在子类中,展示了继承的有用性。
UI controls
并且Streams
也是继承的用处一个很好的例子。
对象的每个实例都是继承有用的具体示例!
如果您专门指的是类继承,那么您现在处于分类法领域,并且这些分类将因使用它们的系统目标而大不相同。动物/哺乳动物示例使用了生物学上常见且希望熟悉的分类法,但是(如您所提到的)对于绝大多数程序设计问题几乎没有用。
因此,尝试一些通用的东西:程序的概念。每个程序都将开始,运行和结束。每个程序都有一个名称和可选的命令行参数。因此,基本的Program类对于启动执行,获取和处理命令行参数,运行主逻辑以及正常关闭非常有用。
这就是为什么这么多面向对象的编程语言提供Program类或行为完全类似于Program类的原因。
class Programm { public static void main(String[] args) { system.out.println('hello world'); }}
是最小的Java程序。当我调用它时,没有程序的实例。程序不继承任何东西。当我启动3个进程(就像您对crhome所做的那样)时,可能会有3个程序,但是在它们各自的内存区域中,仍然只有一个程序。恕我直言,单例意味着“每个进程只有一个实例”,而不是每个机器。如果是这样,就不可能产生单例,没有什么可以阻止您两次运行任何代码。
这是另一个突然出现的例子:
类Element_ { 双atomicWeight;//元素的原子量 double atomicNumber; //元素的原子数 字符串属性;//元素的属性 //其他(如果有) } 同位素扩展Element_ //元素可能存在同位素 { 半衰期加倍; //其他(如果有) }
isotope
不是的特例Elemenet
。我宁愿在拥有Element
财产Isotope
。
我只是给他们看一个真实的例子。例如,在大多数UI框架中,您都从某种“对话框”或“窗口”或“控件”类派生出自己的类。
一个很好的例子是排序中的比较功能:
template<class T>
class CompareInterface {
public:
virtual bool Compare(T t1, T t2) const=0;
};
class FloatCompare : public CompareInterface<float> { };
class CompareImplementation : public FloatCompare {
public:
bool Compare(float t1, float t2) const { return t1<t2; }
};
template<class T>
void Sort(T*array, int size, CompareInterface<T> &compare);
唯一的问题是新手常常认为性能比好的代码更重要...
我的真实示例是车辆:
public class Vehicle
{
public Vehicle(int doors, int wheels)
{
// I describe things that should be
// established and "unchangeable"
// when the class is first "made"
NumberOfDoors = doors;
NumberOfWheels = wheels;
}
public void RollWindowsUp()
{
WindowsUp = true;
}
// I cover modifiers on properties to show
// how to protect certain things from being
// overridden
public int NumberOfDoors { get; private set; }
public int NumberOfWheels { get; private set; }
public string Color { get; set; }
public bool WindowsUp { get; set; }
public int Speed { get; set; }
}
public class Car : Vehicle
{
public Car : base(4, 4)
{
}
}
public class SemiTruck : Vehicle
{
public SemiTruck : base(2, 18)
{
}
}
该示例可以根据您的需要进行详细介绍,并且在车辆上附加了各种属性,以说明您可能要教的修饰符的用法。
这个非哺乳动物,非鸟类,非鱼类的示例可能会有所帮助:
public abstract class Person {
/* this contains thing all persons have, like name, gender, home addr, etc. */
public Object getHomeAddr() { ... }
public Person getName() { ... }
}
public class Employee extends Person{
/* It adds things like date of contract, salary, position, etc */
public Object getAccount() { ... }
}
public abstract class Patient extends Person {
/* It adds things like medical history, etc */
}
然后
public static void main(String[] args) {
/* you can send Xmas cards to patients and employees home addresses */
List<Person> employeesAndPatients = Factory.getListOfEmployeesAndPatients();
for (Person p: employeesAndPatients){
sendXmasCard(p.getName(),p.getHomeAddr());
}
/* or you can proccess payment to employees */
List<Employee> employees = Factory.getListOfEmployees();
for (Employee e: employees){
proccessPayment(e.getName(),e.getAccount());
}
}
注意:只是不要告诉这个秘密:人会延伸哺乳动物。
代数表达式的层次结构怎么样。很好,因为它既包含继承又包含组成:
+--------------------+------------------------+
| Expression |<------------------+ |
+--------------------+----------+ | |
| + evaluate(): int |<---+ | | |
+--------------------+ | | | |
^ | | | |
| | | | |
+--------------+ +---------------+ +-------------+ ...
| Constant | | Negation | | Addition |
+--------------+ +---------------+ +-------------+
| -value: int | | | | |
+--------------+ +---------------+ +-------------+
| +evaluate() | | +evaluate() | | +evaluate() |
| +toString() | | +toString() | | +toString() |
+--------------+ +---------------+ +-------------+
Addition(Constant(5), Negation(Addition(Constant(3),Constant(2))))
(5 + -(3 + 2)) = 0
除了根表达式Constant以外,所有其他表达式都是一个Expression,并且包含一个或多个表达式。
我将以鸟为例
像鸡,鸭,鹰
我将解释它们都有爪,啄和翅膀,但是它们的属性不同。
鸡不能飞,不能游泳,可以吃蠕虫,可以吃谷物
鸭子不能飞,不能游泳,可以吃谷物,不能吃蠕虫
鹰会飞,不会游泳,可以吃蠕虫,不能吃谷物