第七讲 继承与多态

1.

 源码:

class Grandparent {

    public Grandparent() {

        System.out.println("GrandParent Created.");

    }

    public Grandparent(String string) {

        System.out.println("GrandParent Created.String:" + string);

    }

}

class Parent extends Grandparent {

    public Parent() {

        //super("Hello.Grandparent.");

        System.out.println("Parent Created");

       // super("Hello.Grandparent.");

    }

}

class Child extends Parent {

    public Child() {

        System.out.println("Child Created");

    }

}

public class TestInherits {

    public static void main(String args[]) {

        Child c = new Child();

    }

}

运行结果:

修改之前:

修改之后:

在java语言的继承中,在执行子类的构造方法之前,会先调用父类没有参数的构造方法,其目的是为了要帮助继承自父类的成员做初始化操作。子类的构造方法通过super()来调用父类特定的构造方法(如果没有super语句还是会自动调用父类没有参数的构造方法),调用父类特定的构造方法的super语句必须写在子类构造方法的第一行,否则编译时出错,如果父类只定义了有参数的构造方法,而在子类中又没有用super关键字来调用父类的特定构造方法,则编译时出错。

又问:

子类是通过父类继承过来的,所以子类有父类的所有非私有的属性和方法,如果不调用父类的构造方法,那么不能初始化父类中定义的属性,就给父类的属性分配内存空间 ,如果父类的属性没有分配内存空间,那么子类访问父类的属性,就会报错。

2.

自行编写代码测试以下特性(动手动脑):

在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

(1)覆盖方法的允许访问范围不能小于原方法。

(2)覆盖方法所抛出的异常不能比原方法更多。

(3)声明为final方法不允许覆盖。

例如,Object的getClass()方法不能覆盖。

(4)不能覆盖静态方法。

3.

 

          m=d;         //编译正确,因为子类对象可以直接赋给基类变量。

          d=m;        //编译错误,基类对象要赋给子类对象变量,必须执行类型转换(子类对象变量=(子类名)基类对象名;)

          d=(Dog)m;   //编译正确,基类对象要赋给子类对象变量,必须执行类型转换

          d=c;         //编译错误,不同子类之间不能复制

          c=(Cat)m;    //m已经转换成Dog, Dog和Cat子类之间不能转换

4.

(1)运行结果:

(2)解释:

在调用的时候,对象是子类的,就调用子类的方法,对象是父类的,就调用父类的方法。父类对象访问子类成员,调用相同的函数名的函数属于子类的;父类的变量进行相关的原算,但是,如果这时父类变量指向子类对象,继续调用得方法和变量仍然是子类覆盖后的新的变量和方法的,例如如果将代码改为:

则第三个结果为:101

最后一个输出为父类强转为子类对象,调用的是子类的变量和方法输出。

(3)

父类对象可以访问子类的成员,当然只限于”覆盖”发生时,调用的时候,对象是子类的,就调用子类的方法,对象是父类的,就调用父类的方法。当然还有如下特性:

1.当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。这个特性实际上就是面向对象“多态”特性的具体表现。

2.如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。

3.如果子类被当作父类使用,则通过子类访问的字段是父类的.

5.

源码:

class Parent

{

public int value=100;

public void Introduce()
{

System.out.println("I'm father");

}


}

class Son extends Parent
{

public int value=101;

public void Introduce()
{

System.out.println("I'm son");

}

}


class Daughter extends Parent
{

public int value=102;
public void Introduce()
{

System.out.println("I'm daughter");

}

}

public class TestPolymorphism
{


public static void main(String args[])
{

Parent p=new Parent();

p.Introduce();

System.out.println(p.value);

p=new Son();

p.Introduce();

System.out.println(p.value);

p=new Daughter();

p.Introduce();

System.out.println(p.value);


}


}

 结果:

 多态依赖于类型和实现的分离,多用来把接口和实现分离。

6.(多态:多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。)

运行结果如:

虽然猴子和鸽子有数量的变化,定义固定长度的数组使用不方便,长度有限。

(接口)固定数组实现

public class Denglu
{
public static void main(String args[])
{
Feeder f = new Feeder("小李");
// 饲养员小李喂养一只狮子
f.eat();
// 饲养员小李喂养十只猴子
for (int i = 0; i < 10; i++)
{
f.eat1();
}
// 饲养员小李喂养5只鸽子
for (int i = 0; i < 5; i++)
{
f.eat3();
}
}
}
interface Lion
{
abstract void eat();
}
interface Monkey
{
abstract void eat1() ;
}
interface Pigeon extends Lion,Monkey
{
abstract void eat3() ;
}

class Feeder implements Pigeon
{
public String name;
public Feeder(String name)
{
this.name = name;
}
public void eat()
{
System.out.println("我不吃肉谁敢吃肉!");
}
public void eat1()
{
System.out.println("我什么都吃,尤其喜欢香蕉。");
}
public void eat3()
{
System.out.println("我要减肥,所以每天只吃一点大米。");
}
}

运行结果:

原文地址:https://www.cnblogs.com/mm20/p/7804632.html