java中什么是继承-Java 中什么是继承

在 Java 的世界里,继承就像是给房子装了弹簧。干了点活后面又缩回去,这样你不用每次都搬砖,下次只要按个按钮,房子就能自动补全缺漏的局部,就连还能多造个房间。Java 的 `extends` 关键字,就是那个装弹簧的魔术咒。 想象一下,你那会儿写了一个能跑的大型机器人,名字叫 `RobotBase`。目前你想造一辆小车,但小车只是原来的机器人缩小了一半,并且骨架得改一下。
这时候你就得说:“我要继承 RobotBase"。在 Java 里,这写出来就是:`class Robot extends RobotBase`。
这时候的 `RobotBase` 根本不是别的啥,它就是个“爸爸”。Java 规定,子类的名字得跟父类名字一样长,多一个后缀叫 `C`,故此子类叫 `RobotC`。 一旦声明白继承,整个程序就像一个分层的树。根是 `RobotBase`,往下分 `RobotC`。当你在 `RobotC` 里写代码时,要不就特意去写,否则 Java 会自动把 `RobotBase` 里所有没被覆盖的局部给拉过来。
比如 `RobotBase` 里有一个方式 `growUp()`,告诉机器人要长大。你在 `RobotC` 里要是不写,`growUp()` 就会自动执行。
这就是所谓的“继承”,它是让代码复用,而不是让代码抄袭。 这就好比家里有个模板,`Person` 是模板。
你想做 `Adult`,你就写 `class Adult extends Person`。
要是 `Adult` 里没写 `sayHello()`,那 `sayHello()` 就会自动调用。
不需求你每次造新房子都在墙壁上刻字,出于房子自带说明书。 不过继承不是免费的午餐,它也有点像老式游戏,只有这一个版本,配置选项极少。 起初,继承没法与此同时捏捏捏(override)。假设 `RobotBase` 里有个方式 `setName(String name)`,你在 `RobotC` 里写了同样的方式,那会形成啥?Java 报警告诉你:“你如何能写重复的?”你务必在 `RobotC` 里把这个方式改一改,要么干脆删掉。
这就好比你在拼图里填了两次同一个图案,别看你画了两张图,但最终拼出来是一样的,不过其中一张是废纸。
要是你不继承,直接用 `class RobotC { }`,那是另外的故事,从头启动写,但那时候可没那么多共享资源。 继承里有个坑,叫“少继承”要么“多继承”的矛盾。假设 `Parent` 和 `ChildA` 都继承自 `Grand`。`Grand` 里有个方式 `doSomething()`。
要是在 `Parent` 里覆盖这个方式,那 `ChildA` 继承之后,有没有机会覆盖 `Grand` 的方式?答案是肯定的。但这一般是个费事事。
比如你想让 `Parent` 的行为和 `ChildA` 不一样,结局 `ChildA` 又继承了 `Parent` 的 `doSomething()`,那 `Grand` 的方式就被撞墙了,要么被覆盖了。
这就像你给房子加了两层外墙,每一层都想要独立的颜色,结局最终混在一起,哪位也说不清到底哪层的颜色。 好多人犯错的地方在于当作继承是“抄作业”,实际上它是“悄悄复制”。当你写 `class Child extends Base`,你并没有把 `Base` 的代码拷贝下来,你只是告诉编译器:“嘿,别管 `Base` 了,你的新代码要是没处理完,就等我填好。” 再看个数据例子。假设 `Dog` 是 `Pet` 的强壮版。`Pet` 有两只脚,`Dog` 有四只脚。`Pet` 的跑步法是慢的,`Dog` 的跑步法是快的。
你想造只跑得快的四脚动物,继承法最爽。 ```java class Dog extends Pet { // 这里彻底重写跑步法 void runFast() { System.out.println("Woof! Running fast..."); } // 这里没改叫跑,故此记住父类的这个行为 void run() { System.out.println("Woof! Running normal speed..."); } } ``` 要是 `Pet` 只定义了 `run()`,没有 `runFast()`。当你定义 `Dog` 时,编译机会自动把 `Pet.run()` 塞进去。
故此,`Dog` 目前有两条路可选:要么跑快(调用 `runFast()`),要么跑慢(调用 `run()`)。
这就是继承带来的灵活性。 可是,这种自动填坑也有代价。
要是你 `Dog` 要加的坑,`Pet` 已经填满了,那 `Dog` 就得把 `Pet` 的坑挖了,要么干脆新建。
这叫“少继承”,也就是 `extends` 不能与此同时继承两个有冲突的方式。 另外,继承还有一点点费事,就是务必显式重写。
要是你的父类里有个私有方式(private),你在子类里碰巧写出来,编译器会直接报错,出于 Java 不让子类偷偷访问父类的私有方式。你得有意识地去删,要么重写。
这就像你房子有间睡觉那屋,你想把睡觉那屋改成书房,你得先把睡觉那屋的门拆了,不然新房间插不进。 故此,继承不是最好的设计,最好的设计是“组合”。假设你想造一辆既跑得快的车,又装得下大东西的卡车。你肯定不会直接继承一个“快”和“大”的基因,出于那样代码会乱套。你会造一个“快”的车,再造一个“大”的箱,最终把它们拼起来。
这叫接口和组合,比继承更灵活,也没那么多坑。 实战中,继承有时候会过时。
比如目前流行用 Java 8 的 Lambda 表达,要么用泛型,就连直接用 `interface` 来定义行为。
有时候继承是累赘,出于你在父类里写忒多通用代码,子类里全是重复代码。
这时候就需求 `super` 关键字,要么 `extends` 父类的构造方式。 ```java class Car extends Vehicle { // 父类的构造方式 public Car(int price) { super(price); System.out.println("New Car, priced at " + price + " dollars"); } // 重写父类的构造方式,做点特殊的事 @Override protected void makeReady() { System.out.println("Making this car ready to drive."); } } ``` 这里 `super` 就是那个“爸爸”的助手。你在子类构造里用 `super(...)`,就是在告诉爸爸:“爸,帮我把参数传那会儿”。父类的构造逻辑就自动执行了。 总结来说,Java 的继承是力挽狂澜的魔法,也是好办掉坑的陷阱。它让你不用重复造轮子,但要是你把整个房子(父类)都搬到一个新地方,最终发现那个房子的地基(父类的原始设计)跟你要盖的新房子不匹配,那就得重新盖。最好的用法,是把它当成一个“搭积木”的过程,用继承搭框架,再用组合贴墙皮,最终用接口定规矩。想想有没有那种既跑得快又装得下的车?那就得看看你接下来的代码如何设计。
文章版权声明:除非注明,否则均为 静秋号介绍 原创文章,转载或复制请以超链接形式并注明出处。
相关标签: