目录

面向对象编程有三大特性:封装、继承、多态
在类和对象中已经介绍了封装,接下来讲继承
1.继承
1.1为什么要继承
java中使用类对现实世界中的实体进行描述,类经过实例化之后的对象,则可以用来表示现实中的实体,但是事物之间可以会存在一些关联,那么在设计程序是就得进行考虑。
比如,猫和狗
用java语言描述就是:
class dog{
public String name;//名字
public int age;//年龄
public String color;//毛色
public void eat(){
System.out.println("吃东西");
}
}
class Cat{
public String name;//名字
public int age;//年龄
public String color;//毛色
public void bark(){
System.out.println("正在叫");
}
}
我们可以看到他们之中有着重复的内容,那么我们可以将这些共有的内容进行抽取,来实现代码的复用,这就叫继承。
1.2继承的概念
继承机制:是面向对象程序设计是代码可以复用 最重要的手段,它允许程序员在保持原有类的特性上进行扩展,增加新的功能,这样产生的类叫做派生类。
继承主要解决的问题:共性抽取,实现代码复用。
接上的狗和猫,我们可以利用继承的思想,把他们所共有的进行抽取

如下图:狗和猫继承动物的属性。

1.3如何使用继承
我们需要用到extends关键字。
例如:
修饰符 class 子类 extends 父类{
//...
}
对于狗和猫的例子,我们可更改为
class Animal{
public String name;//名字
public int age;//年龄
public String color;//毛色
public void sleep(){
System.out.println("正在睡觉");
}
}
class Animal{
public String name;//名字
public int age;//年龄
public String color;//毛色
public void sleep(){
System.out.println("正在睡觉");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("吃东西");
}
}
class Cat extends Animal{
public void bark(){
System.out.println("正在叫");
}
}
public class test {
public static void main(String[] args) {
Dog dog=new Dog();
// dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
System.out.println(dog.name);
System.out.println(dog.age);
// dog访问的eat()和sleep()方法也是从Animal中继承下来的
dog.sleep();
dog.eat();
Cat cat=new Cat();
cat.bark();
}
}
注意:
1.子类会讲过父类中的成员变量或者成员方法继承到子类中。
2.子类继承父类后,必须要有自己特有的成员,体现出于子类的不同,否则就没有必要继承了。
1.4父类成员访问
1.4.1子类中访问父类的成员变量
1.子类和父类不存在同名的成员变量
class base{
public int a;
}
class derived extends base{
public int b;
public int c;
public void method(){
a=1; //访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
注意: 如果子类有的,优先访问子类,子类没有,就去访问父类看有没有,如果父类也没有,那就报错
2.子类和父类存在同名成员变量
我们再来看下,我们先给父类和子类中的成员变量初始化
class base{
public int a=1;
public int b=2;
}
class derived extends base {
public int b=3;
public int c=5;
public void show() {
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
public class test1 {
public static void main(String[] args) {
derived d = new derived();
d.show();
}
}
//结果:1 3 5
注意:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。
那么,如果我们想访问父类中的成员变量,我们可以用super
class base{
public int a=1;
public int b=2;
}
class derived extends base {
public int a=4;
public int b=3;
public int c=5;
public void show() {
System.out.println(super.a);//父类中的
System.out.println(this.a);//子类中的
System.out.println(super.b);//父类中的
System.out.println(this.b);//子类中的
System.out.println(c); //子类中的
}
}
public class test1 {
public static void main(String[] args) {
derived d = new derived();
d.show();
}
}
1.4.2子类对成员方法的访问
class Base{
public void testA(){
System.out.println("Base:testA()");
}
public void testB(){
System.out.println("Base:testB()");
}
}
class Derived extends Base{
public void testA(){
System.out.println("Derived: testA()");
}
public void testB(){
System.out.println("Derived:testB()");
}
public void testC(){
super.testA();//访问父类中的方法
this.testA();//访问子类中的方法
super.testB();//访问父类中的方法
this.testB();//访问子类中的方法
}
}
public class test3 {
public static void main(String[] args) {
Derived d=new Derived();
d.testC();
}
}
结果:
Base:testA()
Derived: testA()
Base:testB()
Derived:testB()
注意:
1.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。
2.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错
2.this和super的区别
this是对当前对象的引用,super是对当前对象父类的引用
this可以引用当前对象的成员,方法,构造方法
super可以引用当前对象中父类的成员,方法,构造方法。
注意:
1. 只能在非静态方法中使用
2. 在子类方法中,访问父类的成员变量和方法
3.子类的构造方法
class Base1{
public Base1(){
System.out.println("Base");
}
}
class Derived1 extends Base1{
public Derived1(){
//super();
System.out.println("Derived");
}
}
public class test4 {
public static void main(String[] args) {
Derived1 d = new Derived1();
}
}
结果:
Base
Derived
我们可以看到,在实例化子类对象时,子类在构造时,会先调用父类的构造方法,在调用子类的构造方法。为什么会这样?其实在子类的构造方法中,还隐藏着一个语句,super();
既然子类继承了父类中的成员,那么就需要先对父类中的成员进进行初始化,就先调用父类的构造方法,再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。
注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构 造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的 父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出
2.代码块的执行顺序
在类和对象中,最后讲了代码的执行顺序,那我再来看基于继承下,代码的执行顺序
class Base1{
public Base1(){
System.out.println("父类的构造");
}
static{
System.out.println("父类的静态代码块");
}
{
System.out.println("父类的实例化代码块");
}
}
class Derived1 extends Base1{
static{
System.out.println("子类的静态代码块");
}
public Derived1(){
System.out.println("子类的构造方法");
}
{
System.out.println("子类的实例化代码块");
}
}
结果:
父类的静态代码块
子类的静态代码块
父类的实例化代码块
父类的构造
子类的实例化代码块
子类的构造方法
===================
父类的实例化代码块
父类的构造
子类的实例化代码块
子类的构造方法我们可以看到,确实是在类和对象中所想的一致。
3.final关键字
final关键字可以用来修饰变量、成员方法以及类
3.1修饰变量或者字段,表示常量,不能修改
final int a = 1;
a = 20; // 编译出错
3.2修饰类,表示不能被继承
inal public class Animal {
...
}
public class Bird extends Animal {
...
}
// 编译出错
无法对Animal进行继承
3.3修饰方法,表示不能重写
4.继承和组合
和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果。
继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a的关系,比如:汽车
想进一步理解继承和组合,这里可以看看这个网址深入了解继承与组合
本文详细介绍了面向对象编程中的继承概念,包括其原因、如何使用继承、继承中的成员访问规则、this与super的区别以及子类构造方法的执行顺序。同时提及了final关键字在变量、方法和类上的应用,以及继承与组合的区别。

被折叠的 条评论
为什么被折叠?



