定义animal父类的核心是构建可复用、可扩展、行为一致的抽象模型,聚焦共性属性(如name、age)和行为(如eat()、cry()),用protected封装,避免特有逻辑;子类须满足“is-a”语义,正确调用super(),重写方法加@override;多态依赖非final/non-private方法,必要时用abstract强制实现;警惕误用继承、忽略构造顺序及过度抽象。

定义动物父类不是为了写一个“看起来像动物”的类,而是为了建立可复用、可扩展、行为一致的抽象模型。关键不在名字叫Animal,而在它是否真正承载了子类共性、隐藏了不该暴露的细节、并为多态留出空间。
明确父类职责:只管通用,不越界
父类应聚焦所有动物共有的属性和行为,比如名字、年龄、进食、发声等。这些属性通常用protected或提供getter/setter访问,避免直接public暴露,也不宜用private导致子类无法合理复用。
- 属性如
name、age建议设为protected——子类可直接使用,又不对外公开 - 方法如
eat()、cry()应设计为具体实现(非abstract),除非你确定所有子类必须差异化实现且无默认逻辑 - 避免在父类中定义猫抓鼠、狗看门这类特有行为——它们属于子类职责,强行塞进父类会破坏单一职责
子类继承要体现“is-a”关系
继承不是为了代码省事,而是语义真实。只有当“猫是一种动物”“狗是一种动物”成立时,Cat extends Animal才合理。若出现“汽车是一种动物”,说明抽象出了问题。
- 子类构造器必须调用
super(...)初始化父类状态,确保name、age等被正确赋值 - 重写父类方法(如
eat())时,用@Override标注,既明确意图,也由编译器校验签名一致性 - 特有方法(如
catchMouse()、watchDoor())只在子类中定义,不污染父类接口
为多态预留接口:运行时行为由实际类型决定
多态的价值在于统一处理不同子类对象。例如用Animal a = new Cat(); a.eat();调用时,执行的是Cat重写的逻辑,而非Animal的默认实现。
- 确保父类方法可被重写(非
final、非private、非static) - 测试时可尝试用父类引用指向不同子类实例,验证同一方法调用产生不同输出
- 若需强制子类实现某行为(如每种动物叫声不同),可将方法声明为
abstract,同时把父类改为abstract class
常见陷阱与应对
初学者容易把继承当成“复制粘贴简化版”,结果写出高耦合、难维护的结构。
-
误用继承代替组合:比如“鸟有翅膀”不等于“鸟继承翅膀”,应把
Wing作为成员变量,而非父类 -
忽略构造顺序:子类构造器第一行必须是
super()或this(),否则编译失败 -
过度抽象:一开始就定义
LivingBeing→Animal→Mammal→Dog多层继承,往往得不偿失;从Animal直出Cat/Dog更务实











