java学习 -- 继承

    xiaoxiao2022-07-14  152

    继承小例子

    class Human { public String name = "小黄"; // 姓名 public int age = 22; // 年龄 } class Student extends Human { public double score = 66.6; // 分数 } class Graduate extends Student { public String mentor = "小勇"; // 导师 } public class TestExtends { public static void main(String[] args) { Graduate gd = new Graduate(); System.out.printf("%s %d %f %s\n", gd.name, gd.age, gd.score, gd.mentor); } }

    继承

    一个新类从已有的类那里获得其已有的属性和方法,这种现象叫类的继承这个新类被称为子类,也叫派生类,已有的那个类叫做父类,也叫做基类继承的好处 代码得到极大的重用形成一种类的层次体系结构为多肽创造条件 继承的实现方式 class SubClass extends SuperClass {} Java只支持单继承,不允许多重继承单继承就是一个类只能有一个父类多继承就是一个类可以有多个父类可以有多层继承,即一个类可以继承某一个类的子类,如类B继承了类A,类C又可以继承类B,那么类C也间接继承了类A。子类可以继承父类所有的成员变量和成员方法,但子类永远无法继承父类的构造方法。在子类的构造方法中可使用语句super(参数列表)调用父类的构造方法。

    继承的访问控制权限

    同包继承权限问题(重点)

    子类的所有方法内部都可以访问父类除私有成员以外的所有成员,所谓子类的所有方法也包括子类的私有方法通过子类对象名可以访问 父类除私有成员外的所有成员子类本身的除私有成员外的所有成员附注:私有成员包括私有属性和私有方法 子类可以继承父类除私有成员以外的所有成员父类的私有成员不可以被子类继承,其他的成员都可以被子类继承不同包之间的继承问题,后面还会讨论 // 说明了:子类内部可以访问父类非私有的成员,私有成员无法被子类方法访问 // 通过子类对象名只能访问从父类继承过来的非私有成员 // 总结:私有不能被继承 // 私有物理上已经被继承过来了,只不过逻辑上程序员不能去访问它 // 因此继承必须慎重,否则会浪费内存 class A { public int i; protected int j; private int k; public void g() { } private void s() { } protected void b() {} } class B extends A { private void g() { i = 10; j = 20; // k = 30; // error 私有属性不能被继承 g(); b(); // s(); // error 私有方法不能被继承 } public void f() { i = 10; j = 20; // k = 30; // error 私有属性不能被继承 g(); b(); // s(); // error 私有方法不能被继承 } } class M { public static void main(String[] args) { B bb = new B(); bb.i = 20; bb.j = 30; bb.b(); bb.g(); // bb.s(); // error // bb.k = 22; // error } }

    继承的原则

    何时选择继承? 一个很好的经验:“B是一个A吗?”如果是则让B做A的子类注意:经常犯的错误,A有一个B吗?例如让汽车轮子成为汽车的子类是错误的

    不同访问修饰符

    publicprotecteddefaultprivate同包同类√√√√访问同包不同类√√√同包不同类继承√√√不同包继承√√访问不同包无任何关系的类√

    super关键字

    class A { public int i; public int j; } class B extends A { public int k; public B() {} public B(int i, int j, int k) { this.i = i; // 一定要明白为什么i前面可以加this this.j = j; // 因为i是通过A继承过来的,所以B里面也有i,所以可以加this this.k = k; } } public class TestSuper { public static void main(String[] args) { B bb = new B(1, 2, 3); System.out.printf("%d, %d, %d\n", bb.i, bb.j, bb.k); } } // 说明了:子类B的构造函数中调用super,可以调用父类A的构造函数 class A { public int i; public int j; } class B extends A { public int k; public B() {} public B(int i, int j, int k) { // A(i, j); // error super(i, j); // OK this.k = k; } } public class TestSuper { public static void main(String[] args) { B bb = new B(1, 2, 3); System.out.printf("%d, %d, %d\n", bb.i, bb.j, bb.k); // => 1, 2, 3 } } // super常犯错误 class A { public int i; } class B extends A { public int j; public B(int i, int j) { super(i); // error 因为父类A中没有有参构造方法 this.j = j; } public void f(int i) { // 普通方法 // super(i); // error 普通方法中不能调用父类的构造方法 } } public class TestSuper { public static void main(String[] args) { B bb = new B(1, 2, 3); System.out.printf("%d, %d, %d\n", bb.i, bb.j, bb.k); } } // super常犯错误 class A { public int i; public A(int i) { this.i = i; } } class B extends A { public int j; public B(int i, int j) { //当你不写任何super时,系统会自动调用super(),这个时候因为父类A中有一个有参的构造方法,没有无参的,所有报错 this.j = j; } public void f(int i) { // 普通方法 // super(i); // error 普通方法中不能调用父类的构造方法 } } public class TestSuper { public static void main(String[] args) { B bb = new B(1, 2, 3); System.out.printf("%d, %d, %d\n", bb.i, bb.j, bb.k); } } // super常犯错误 class A { public int i; public A() {} public A(int i) { this.i = i; } } class B extends A { public int j; public B(int i, int j) { this.j = j; super(i); // error 因为super()要为第一条语句 super(); // error 因为一个构造函数里面只能调用一个supper } public void f(int i) { // 普通方法 // super(i); // error 普通方法中不能调用父类的构造方法 } } public class TestSuper { public static void main(String[] args) { B bb = new B(1, 2, 3); System.out.printf("%d, %d, %d\n", bb.i, bb.j, bb.k); } }

    总结:

    每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错如果显式的写出super()语句,则必须保证该语句是第一条语句,否则会出错super()如果不写,则编译器会自动添加,所以此时如果父类没有无参的构造函数就会出错。既可以显式的写super(),前提是父类必须有无参的构造函数;也可以显式地写super(实参),前提是父类必须有带参数的构造函数调用父类的构造函数的语句必须借助于supper,不能直接写父类的类名一个构造函数不能写多个super语句

    方法的重写

    class A { public void f() { System.out.printf("AAAA\n"); } } class B extends A { public void f() { super.f(); // 调用从父类继承过来的f方法 System.out.printf("BBBB\n"); } } public class TestOver { public static void main(String[] args) { B bb = new B(); bb.f(); // => AAAA BBBB } } class A { public void f() { System.out.printf("AAAA\n"); } } class B extends A { public void f() { // 重写父类方法 System.out.printf("BBBB\n"); } } public class TestOver { public static void main(String[] args) { B bb = new B(); bb.f(); // => BBBB } } 方法重写:指在子类中重新定义父类中已有的方法重写方法必须二和被重写方法具有相同的方法名称、参数列表和返回值类型子类中不允许出现于父类同名同参数但不同返回类型的方法,如果出现,编译时会报错。重写方法时,不能使用比父类中被覆盖的方法更严格的访问权限

    方法重写实例

    class Human { private String name; private int age; public Human() { } public Human(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getInfo() { String strInf = name + ":" + age; return strInf; } } class Student extends Human { public String school; public Student() {} public Student(String name, int age, String school) { // this.name = name; //error 因为他们是私有的 // this.age = age; super(name, age); this.school = school; } public void setSchool(String school) { this.school = school; } public String getInfo() { // String strInf = name + ":" + age + ":" + school; // error ,因为是私有的 String strInf = super.getInfo() + ":" + school; return strInf; } } public class TestStudent { public static void main(String[] args) { Student st1 = new Student("张三", 22, "酱菜"); System.out.printf("%s\n", st1.getInfo()); // => 张三:22:酱菜 } }
    最新回复(0)