I.子类可以重写父类的方法:
1、方法名称要一样
2、返回值数据类型要一样
3、所使用的参数列表要一样,也就是形参必须一直
4、访问修饰符只能越来越开放,不能越来越封闭(比如从private到public)
重写父类的方法:
public class A {
public void show(String name){
System.out.println("父类的show方法");
}
}
public class B extends A{
public void show(String name){
System.out.println("子类的show方法");
}
}
这里B类继承了A类,重写了A类的show方法(方法名一直,返回值一直,形参一直)
public class Demo{
public static void main(String[] args) {
B b = new B();
b.show("parameter");
}
}
所以使用B的show方法,那么就会输出
子类的show方法
使用父类的方法:
如果上面的代码修改一下子类show方法的形参,改为整形呢?
public class B extends A{
public void show(int paramenter){
System.out.println("子类的show方法");
}
}
继续使用上面的Demo代码
public class Demo{
public static void main(String[] args) {
B b = new B();
b.show("parameter");
}
}
就会输出:
父类的show方法
因为子类并没有重写父类的show方法,只是创建了一个新的show方法,形参为整形,所以使用了父类的show方法。
(2)构造方法的继承 创建子类对象的时候,会默认调用父类的无参构造方法:
public class A {
public A(){
System.out.println("调用了父类的无参构造方法");
}
}
//A的子类
public class B extends A{
public B(){
System.out.println("调用了子类的无参构造方法");
}
}
//测试类
public class Demo{
public static void main(String[] args) {
B b = new B();
}
}
输出结果就是:
调用了父类的无参构造方法
调用了子类的无参构造方法
对super和this进行一次复习~下面代码的执行结果是什么呢?
public class A {
public A(){
this(123);
System.out.println("调用了父类的无参构造方法");
}
public A(int parameter){
System.out.println("调用了父类的有参构造方法");
}
public void show(){
System.out.println("调用了父类的show方法");
}
}
//A的子类
public class B extends A{
public B(){
this(123);
System.out.println("调用了子类的无参构造方法");
}
public B(int parameter){
System.out.println("调用了子类的有参构造方法");
super.show();
}
}
//测试类
public class Demo{
public static void main(String[] args) {
B b = new B();
}
}
我们再巩固一下这个知识点,先执行父类的无参构造方法,然后执行子类的无参构造方法。往下拉对一下答案哦
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
调用了父类的有参构造方法
调用了父类的无参构造方法
调用了子类的有参构造方法
调用了父类的show方法
调用了子类的无参构造方法
因为我们在父类的无参构造方法里面,通过this关键字,调用了父类的有参构造方法,所以先执行的是父类的有参构造,然后调用结束,回到无参构造方法这里,输出了父类的无参构造方法。然后父类的无参构造方法执行结束了,就到子类的无参构造方法。子类的无参构造方法也是通过this关键字,调用了子类的有参构造方法,输出了子类的有参构造方法,然后再通过super关键字,调用了父类的show方法,然后执行完毕,再回到子类的无参构造方法继续执行,所以在这段代码里面,子类的无参是最后输出的。
(3)继承有单继承和多重继承 I.单继承是指一个子类只能由一个父类(如果一个类没有继承父类,那么它的默认父类就是Object类)。
II.多重继承是指子类继承的父类可以还有父类的父类,比如 C extends B,B extends A,就是B继承A,C也继承了B,相当于C继承了B和A
举个例子:
public class A {
public void show(A a){
System.out.println("A and A");
}
}
public class B extends A{
public void show(A o){
System.out.println("B and A");
}
public void show(B o){
System.out.println("B and B");
}
}
public class C extends B{
public void show(C o){
System.out.println("C and C");
}
}
然后我们分别创建C的对象,调用三个show方法来查看
C c = new C();
c.show(new A());
c.show(new B());
c.show(new C());
因为C里面没有形参为A的show方法,所以先到父类B里面查找,刚好父类B类里面重写了B父类A的show方法,所以调用的是B里面形参为A的show方法,如果B里面没有重写形参为A的show方法,那么就会到B的父类A里面查找有没有形参为A的show方法,如果有,就调用该方法。
这段show的运行结果是:
B and A
B and B
C and C
多态
先来做个简单的科普:
Father object = new Son();
父类引用指向子类对象,其实是 该对象object,数据类型是Father(父类),它只能调用A里面的成员变量和成员方法,那为什么是通过实例化Son(new Son();)来创建呢?
这样可以通过子类重写父类的方法,实现调用子类Son的方法,但是对象object只能使用Father里面有的成员变量和成员方法。
(1)父类引用指向子类对象 有以下代码:
public class A {
}
//A的子类
public class B extends A{
}
//测试类
public class Demo{
public static void main(String[] args) {
A b = new B();
}
}
这就是典型的父类引用指向子类对象,这里的父类就是A,引用了 它的子类B。
(2)通过多态创建的对象,只能使用父类的成员属性和成员方法 我们在父类引用指向之类对象中,创建了一个实例化对象 b,它的属性是B类的,但是它的数据结构是A类的。也就是说,b只能用A里面有的成员属性和方法。
先看不是多态创建的对象:
public class A {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//A的子类
public class B extends A{
//B继承了A,所以B有A的所有成员方法和成员变量
public void check(){
System.out.println(getName()+",年龄是"+getAge());
}
}
//测试类
public class Demo{
public static void main(String[] args) {
B b = new B();
b.setName("十三");
b.setAge(18);
b.check();
}
}
输出结果是
十三,年龄是18
这就是一个基本的继承,子类继承父类的所有成员属性和成员方法。
再看看通过多态创建的对象:
public class A {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//A的子类
public class B extends A{
//B继承了A,所以B有A的所有成员方法和成员变量
public void check(){
System.out.println(getName()+",年龄是"+getAge());
}
}
//测试类
public class Demo{
public static void main(String[] args) {
A b = new B();
b.setName("十三");
b.setAge(18);
b.check();
}
}
你如果自己写代码,你会发现b.check();这里报错了。
会提示:
Cannot resolve method 'check' in 'A'
就是在A中找不到check()方法。
因为是通过多态创建的对象b,它只有A里面的成员属性和成员方法,也就说只能用A里面有的东西。
那么我们可能会疑惑,如果只能用A里面的成员属性和成员方法,那么我们为什么要给它实例化B呢( new B(); )?
(3)子类重写父类方法 如果在子类中重写了父类的方法,那么通过多态创建的对象,在调用父类的被子类重写了的方法的时候,会调用子类重写了父类的这个方法。
比如:
public class A {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void check(){
System.out.println(name);
}
}
//A的子类
public class B extends A{
//B继承了A,所以B有A的所有成员方法和成员变量
public void check(){
System.out.println(getName()+",年龄是"+getAge());
}
}
//测试类
public class Demo{
public static void main(String[] args) {
A b = new B();
b.setName("十三");
b.setAge(18);
b.check();
}
}
这时候check()方法就没有报错了,因为A类有check方法,但是它是通过实例化B( new B(); )来得到的对象,所以如果B里面重写了check的话,调用check就会调用B里面的check();
至于为什么要这样做?涉及到设计模式耦合性的问题,到总结那里大概过一下多态的优点即可。
(4)类型转换 子类对象可以当作父类对象来用
父类对象不可以当作子类对象来用
如果父类引用指向子类对象,那么该对象可以通过强制转换成子类对象来使用,如:
public class A {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void check(){
System.out.println(name);
}
}
//A的子类
public class B extends A{
//B继承了A,所以B有A的所有成员方法和成员变量
public void check(){
System.out.println(getName()+",年龄是"+getAge());
}
}
//测试类
public class Demo{
public static void main(String[] args) {
A b = new B();
b = (B) b;//这样就回到了继承那边的知识点,子类可以调用父类所有的成员变量和方法~
b.setName("十三");
b.setAge(18);
b.check();
}
}
(5)总结
如果看完了继承和多态还是觉得绕的话,那么记住如果有用到方法,那么就看=右边的实例对象,如果要用到属性,那么就用=左边
也就是 Father object = new Son();
如果用到了方法,就到Son()里面去找,如果用到了属性,那么就到Father里面找。
多态的必要条件:
I.继承
II.重写(子类继承父类之后重写父类的方法)
III.父类引用指向子类对象
Father object = new Son();
多态的优点:
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
巩固一下知识点!~
public class A {
public void show(A object){
System.out.println("A and A");
}
public void show(D object){
System.out.println("A and D");
}
}
public class B extends A{
public void show(B object){
System.out.println("B and B");
}
public void show(A object){
System.out.println("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Demo{
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.print("1:");
a1.show(b);
System.out.print("2:");
a1.show(c);
System.out.print("3:");
a1.show(d);
System.out.print("4:");
a2.show(b);
System.out.print("5:");
a2.show(c);
System.out.print("6:");
b.show(d);
System.out.print("7:");
b.show(b);
System.out.print("8:");
b.show(c);
System.out.print("9:");
b.show(d);
}
}
问,1-9分别会输出什么?(自己答完可以跑一遍这个程序得到答案)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)