• 欢迎光临~

Java程序设计语言第四讲,继承与多态

开发技术 开发技术 2022-10-21 次浏览

Java中通过extends实现继承

并且,Java中只允许单继承,从而避免里多继承中可能产生的父类属性冲突问题。

子类自动拥有父类声明 的public和protected的成员。

 

继承条件下的访问权限:

public:外界可自由访问

private:外界不可访问

protected:同一包中的子类都可以访问,另一包中的子类(派生于同一个父类)也可以访问

default:如果不指明任何权限,则默认同一包中的类可以访问

 

继承条件下构造方法的调用:

代码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 Main{
public static void main(String args[]) {
Child c = new Child();
}
}
运行截图:
Java程序设计语言第四讲,继承与多态

 

 代码2:

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 Main{
public static void main(String args[]) {
Child c = new Child();
}
}
运行截图:
Java程序设计语言第四讲,继承与多态

 

 代码3:

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 Main{
public static void main(String args[]) {
Child c = new Child();
}
}
运行截图:
Java程序设计语言第四讲,继承与多态

 

 ****通过super调用基类构造方法是必须是子类构造方法中的第一个****

 

通过final声明的类是不允许继承的**

以final声明的方法不允许覆盖,以final声明是变量不允许更改,利用final可以设计出一种在特殊的只读的不可变类(基创建之后不允许修改对象属性,也无法从此类派生出子类,比如String)

相较于其他类,不可变类可以更加方便和安全地用于多线程环境中,同时因为访问它们可以不加锁,因而能提供较高的性能。

 

在子类如果要调用父类中被覆盖的方法可以使用super关键字(super还可以在子类中显式调用父类构造方法)

 

Java覆盖方法的语法规则:

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

2,覆盖方法所抛出的异常不能比原方法多

3,声明为final的方法不允许覆盖

4,不能覆盖静态方法

 

多态最本质的特征就是父类(或接口)变量可以引用子类(或实现了接口的类)对象;既子类对象恶意被父类引用

例如:Parent p = new Child();(可以让更一般的对象容纳更具体的对象)

特别,Java类库的最顶层类是Object,因此每个对象都可以赋值给Object变量

 

子类对象可以直接赋值给基类变量,但是基类变量赋值给子类变量是必须要进行类型转换

子类对象变量 = (子类名)基类对象名;(并不是所有基类都可以经管类型转换后赋值给子类)

instanceof可以用于判断类型是否可以进行转换

代码:
public class Main{
public static void main(String[] args) {
//声明hello时使用Object类,则hello的编译类型是Object,Object是所有类的父类
//但hello变量的实际类型是String
Object hello = "Hello";
//String是Object类的子类,所以返回true。
System.out.println("字符串是否是Object类的实例:" + (hello instanceof Object));
//返回true。
System.out.println("字符串是否是String类的实例:" + (hello instanceof String));
//返回false。
System.out.println("字符串是否是Math类的实例:" + (hello instanceof Math));
//String实现了Comparable接口,所以返回true。
System.out.println("字符串是否是Comparable接口的实例:" + (hello instanceof Comparable));
String a = "Hello";
//String类既不是Math类,也不是Math类的父类,所以下面代码编译无法通过
//System.out.println("字符串是否是Math类的实例:" + (a instanceof Math));
}
}
运行结果:
Java程序设计语言第四讲,继承与多态

 

 

代码:

class Mammal{}
class Dog extends Mammal {}
class Cat extends Mammal{}

public class Main{
public static void main(String args[]) {
Mammal m;
Dog d=new Dog();
Cat c=new Cat();
m=d;
//d=m;//基类赋值给需要进行类型转换
d=(Dog)m;
//d=c;//Dog类和Cat类没有关系,不可以进行类型转换
//c=(Cat)m;//此时m为Dog类,无法赋值给Cat类实例
}
}
没有截图;上段代码中被注释部分都是不可以运行的,原因已经注释在相应语句后面了

看一段离谱的的代码:
public class Main{
public static void main(String[] args) {
Parent parent=new Parent();
parent.printValue();
Child child=new Child();
child.printValue();

parent=child;
parent.printValue();

parent.myValue++;
parent.printValue();

((Child)parent).myValue++;
parent.printValue();

}
}

class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}
运行结果:

Java程序设计语言第四讲,继承与多态

 

 它的结果和我运行之前的猜想有一定的出入,后来对照仔细分析了一下:最开始的两条因为调用的都是自己的方法所以输出的是自己的类中的数值,这里没什么问题;第三句将子类对象赋值给父类对象,此时父类对象标识的是更加具体的子类对象,所以调用的是子类的构造方法(比如兔子是草食性动物,这里草食性动物是父类,兔子是更加具体的子类,此时兔子类中的对象小白兔的食物就是草而不是包括树木等在内的更加广泛的植物);第四句parent.myValue++;中的parent.myValue指的依旧是父类中的变量(依旧是兔子的例子,虽然将兔子的对象变量赋值给了草食性动物,但是增加草食性动物的种类时不会影响到兔子类,如果想增加兔子类的种类则需要特殊说明是新增加的种类兔子类的分支),所以parent.myValue++;只是对父类中的myValue进行了自增,不会形象到子类;第五局的原理在上一句其实已经说到了,想要通过通过父类对象对子类变量进行更改就需要将服了转换为子类进行操作

将上边的句子进行总结之后就是:

1,当子类与父类拥有一样的方法且让一个父类变量去引用一个子类对象是,到底调用哪个方法是由对象本身的“真实性”决定的,也就是说,对象 子类它就调用子类的方法,对象的父类他就调用父类的方法

2,如果子类与父类有相同的字段,则子类的字段会代替或隐藏父类的字段,子类方法中访问的是子类的字段(可以通过super访问父类字段)

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

 

关于抽象类,抽象方法的说法和C是差不多的。不过这里是将abstract作为关键字

 

因为在Java中不允许多继承,所以为了克服其所带来的问题Java中引入了接口的概念

应以一个接口应采用关键字interface,实现一个接口应用implements

接口的成员方法自动成为public,而字段自动成为static和final的

如果接口不声明为public,则自动变为package

一个类也可以同时实现多个接口

【使用方法:接口类型 接口类型的变量 = new 实现了接口的具体类型  IFood f = new Duck(); 】

 

接口与抽象类的区别:

1,抽象类是一个不完全的类,而接口之是表面类应该具有哪些“外部”特征,不涉及任何实现细节

2,接口基本上不具备继承的任何特点,它仅仅承诺了外界能够调用的方法

3,一个类一次可以实现若干个接口,但是一个类只能继承一个父类

public class ParentChildTest {public static void main(String[] args) {Parent parent=new Parent();parent.printValue();Child child=new Child();child.printValue();parent=child;parent.printValue();parent.myValue++;parent.printValue();((Child)parent).myValue++;parent.printValue();}}
class Parent{public int myValue=100;public void printValue() {System.out.println("Parent.printValue(),myValue="+myValue);}}class Child extends Parent{public int myValue=200;public void printValue() {System.out.println("Child.printValue(),myValue="+myValue);}}
程序员灯塔
转载请注明原文链接:Java程序设计语言第四讲,继承与多态
喜欢 (0)