第七章类的继承、多态、抽象类和接口

文章介绍了Java中的继承概念,强调了一个类只能继承一个父类,展示了继承的语法和示例。此外,讲解了Object类及其常用方法如equals和toString。接着,讨论了对象类型的转换,包括向上转型和向下转型。文章还提到了instanceof关键字用于判断对象类型,以及方法的重载原理。最后,探讨了final关键字在变量、方法和类中的应用,并解释了多态性如何增强程序的扩展性和易维护性。
摘要由CSDN通过智能技术生成

一:类的继承
继承在面对向对象开发思想中是一个非常重要的概念,它使整个程序架构具有一定的弹性在程序中复用一些已经定义完善的类,不仅可以减少软件开发周期,也可以提高软件的可维护性和可扩展性本章节将详细

java语言中 每个类只可以继承一个父类

extends 继承语句

父类没有任何变化

public class 父类类名{
 
}
因为java只支持继承 即一个类只能有一个父类 所以一下代码是错的

class Child extends Parent1 Parents2{}
例题7.1代码

package 第七章继承;
 
public class Parent {//创建父类
//父类
    public Parent(){//
        System.out.println("parnt类的构造方法");//输出
    }
}
public class Child extends Parent{//继承父类的整型变量
    public Child() {
        System.out.println("Child的构造方法");//输出
    }
}
public class Demo {
public static void main(String[]args) {//主方法
    new Child();//新建构造方法
}
}

运行结果图

子类 需要继承分类

public class 子类类名 extends 父类类名 {
}

new 调用构造方法

super//父类的意思//继承的另外一种意思

例题7.2 在打电话的基础上衍生出手机类

public class Telephone {//父类
    String button ="button:0~9";//成员属性  10个按建
    void call(){//拨打电话功能
        System.out.println("开始拨打电话");//输出
    }
}
public class  Mobile extends Telephone {//extends 继承父类
    String screen ="screen:液晶电视";//成员属性
}
public class Demo2 {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Mobile motto=new Mobile();//调用构造方法
        System.out.println(motto.button);//输出
        System.out.println(motto.screen);//输出
        motto.call();
    }
 
}

运行结果图

 二:Object类
所有没有指定父类就是Object

只有子类可以重写父类方法

重写:返回参数相同 方法名相同 传入方法相同 只是方法体不同

Object类中包括clone(),finalize(),equals(),toString()等方法 其中常用的两个方法是equals()和toString()方法由于所有的类都是Object类的子类 所以任何类都可以重写Object类的的方法

下面详细描述了Object类中的几个重要方法

1:getClass方法

getClass()是Object类定义的方法,他会返回对象执行class实例 然后使用此实例调用geiName()方法可以去的类的名称,语法如下

getClass().gername();
可以将getClass()方法与toString()方法的联合使用

2:toString()方法

toString()方法的功能是将一个对象返回为字符串的形式 他会返回一个String实例 在实际的应用中通常重写toString()方法 为对象提供一个特定的输出模式当这个类转换成字符串或字符串链接时 将自动调用重写的toString()方法如下例题7.3让学生的自我介绍 , 使用重写toString方法
代码

package 第七章继承;//toStudent
 
public class Student {//类名
    String name;//成员变量name   名字
    int age;//成员变量  年纪
    public Student(String name,int age) {//定义成员变量
        this.name = name;//将参数赋值给成员变量
        this.age=age;//将参数赋值给成员变量
    }
    public String toString() {//转化为共用字符串类型
        return"我叫"+name+",今年"+age+"岁.";
    }
public static void main(String[]args) {//主方法 
    Student s1 =new Student("张三",16);//新建构造对象方法
    System.out.println(s1);//输出
    Student s2 =new Student("lisi",19);//新建构造对象方法
    System.out.println(s2);//输出
}
}

运行结果

3:equals()方法

使用equals方法

public class People {
    int id;//整型 身份证号码
    String name;//字符串 名字
    
    public People(int id,String name) {//
    this.id=id;//将参数值赋予给类中成员变量
    this.name=name;//将参数值赋予给类中成员变量
    }
    public boolean equals(Object obj) {//重写Object类中的equals()方法
        if(this==obj)//如果参数与本类是同一个对象
            return true;
        if(obj==null)//如果参数是cull
            return false;
        if(getClass()!=obj.getClass())//如果参数与本类类型不同
            return false;
        People other =(People)obj;//将参数强转成本类对象
        if(id!=other.id)
            return false;
        return true;
}
public String toString() {//重写Object类的toString()方法
    return name;
}
public static void main(String[]args) {
    People p1 = new People(220,"tom");
    People p2 = new People(220,"汤姆");
    People p3 = new People(330,"张三");
    Object o= new Object();
    System.out.println(p1+"与"+p2+"是否为同一个人?");
    System.out.println("equals()方法的结果:"+p1.equals(p2));
    System.out.println("==运算符的结果:"+(p1==p2));
    
    
    System.out.println();
    System.out.println(p1+"与"+p3+"是否为同一个人?");
    System.out.println(p1.equals(p3));
    System.out.println(p1+"与"+o+"是否为同一人?");
    System.out.println(p1.equals(o));
}
}


运行结果图

三:对象类型的转换
对象类型的转换在java编程中遇到,主要包括向上转型和向下转型操作。本届将详解讲解对象类型转换的内容

向上转型

向上转型可以理解为将子类类型的对象转换为父类类型的对象,即把子类类型的对象直接赋值给父类类型的对象进而实现按照父类描述子类的效果

向上转型:将子类的对象赋值给父类的对象引用

自动类型转换

Animal a=new Animal();

自动类型转换

构建一个Animal的对象 赋值给Animal的a;

向下转型:将父类的对象赋值给子类对象引用

向下转型的时候需要进行强制类型转换

强制类型转换        

Dog a=(Dog)new Animal();

强制转换需要加()中加

四:使用instanceof关键字判断对象类型
对象名instanceof 类名

判断对象是否属于一个类或其子类

package 第七章继承;
class Quadrangle{}
class Square extends Quadrangle{}
class Circular{}
    public class Dome5 {
    public static void main(String[] args) {
     Quadrangle q=new Quadrangle();//四边形对象
     Square s=new Square();//正方形对象
     System.out.println(q instanceof Square);//判断四边形是否为正方形的子类
     System.out.println(s instanceof Quadrangle);//判断正方形是否为四边形的子类
     System.out.println(q instanceof Circular);//判断正方形是否为圆形的子类
    }
    }
    
}

因为四边形类和圆形类没有继承关系,因此两者不能使用instanceof关键字进行比较,否则会发生"不兼容"错误。如果删除或注释掉这行代码,运行结果如下:

五:方法的重载
第六章中我们曾学习过构造方法 ,知道构造方法的名称是由类名决定,所以构造方法只有一个格名称。 如果希望以不同的方式俩实例化对象,就需要使用u东哥构造方法来完成 由于这个构造方法都需要根据类名进行命名 为了让方法名相同 而形参不同的构造方法同时存在必须用到方法重载  虽然方法重载起源与构造方法 但是它可以应用在其他方法中

方法的重载就是在同意给类中允许存在的一个以上的同名方法,只要这些方法的参数个数或类型不同即可 详细类容如例题7.8

方法名相同  参数不同;

顺序不一样也叫做参数不同

变量名不重要 类型重要

不定长参数的底层参数是数组

package 第七章继承;
 
public class OverLoadTest {
    public static int add(int a,int b) {//定义一个方法 
        return a+b;
    }
public static double add(double a,double b) {//与方法名成相同,参数类型不同
    return a+b;
}
public static int add(int a) {//与第一个方法相同参数类型不同
    return a;
}
public static int add(int a,double b) {//先int参数后double参数
    return a;//输出int参数
}
public static int add(double a,int b) {//先double参数后int参数
    return b;//输出int参数值
}
public static int add(int...a) {
    int s =0;
    for(int i=0;
            i<a.length;i++) {
        s+=a[i];
    }
    return s;
}
public static void main(String args[]) {
    System.out.println("调用add(int,int)方法:"+add(1,2));
    System.out.println("调用add(double,double)方法:"+add(2.1,3.3));
    System.out.println("调用add(int)方法:"+add(1));
    System.out.println("调用add(int,double)方法:"+add(5,8.0));
    System.out.println("调用add(double,int)方法:"+add(5.0,8));
    
    System.out.println("调用不定长参数方法"+add(1,2,3,4,5,6,7,8,9));
    System.out.println("调用add(double,int)方法:"+add(1));
}
}


 运行结果图

根据书上图7.6所示的构成方法重载条件 ,可以总结出编译器时利用方法名,方法个参数类型和参数的个数,参数的顺序来确定类中的方法是否唯一 方法的重载是的方法一种以的名称被管理使程序代码更有条理  。在谈到参数个数可以确定连个该方法是否具有重载关系,会先想到定义不定的长的参数方法 ,不确定长方法的语法入下

返回值 方法名(参数数据类型...参数名称)
 例题7.9使用不定长参数重载方法并输出返回值

7.9跟7.8类似其中加了for循环让每个参数做循环参数

六:final关键字
final被译为“最后的” “最终的”final时java语言中的关键字, 凡是被final关键字修饰过的内容都是不可改变的

1.final变量

final关键字用于修饰常量 

final关键字可用于声明变量,一旦该变量被设定 就不可以在改变该变量的值。通常由final定义的变量为常量如以下语句

final doublie P1= 3.14;
final修饰方法-----该方法不可以被重写

final修饰类-----该类不能被继承

Mymath也不能被重写和继承

当在程序中使用到PI这个常量时,它的值就是3.14.如果在程序中再次对定义为final的常量赋值,编译器将不会接受。
final关键字定义的变量必须在声明时对其进行赋值操作。final除了可以修饰基本数据类型的常量,还可以修饰对象引用。由于数组也可以被看作一个对象来引用,所以final可以修饰数组。一旦一个对象引用被修饰为final后,它就只能恒定指向一个对象,无法将其改变以指向另一个对象。一个既是static又是final的字段只占据一段不能改变的存储空间。

public class cost {
    static final double PI=3.1415926535;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("圆周率的值为:"+PI);
        System.out.println("半径为3的圆的周长为:"+(2*3*PI));
        PI= 3.1415927;(报错)
    }
 
}


2.final方法

将方法定义为 final类型,可以防止子类修改父类的定义图7.7 修改final常量时发生的编译错误与实现方式,同时定义为final的方法的执行效率要高于非final
方法。在修饰权限中曾经提到过private修饰符,如果一个父类的某个方法被设置为private,子类将无法访问该方法,自然无法覆盖该方法。也就是说,一个定义为private的方法隐式被指定为final类型,因此无须将一个定义为private的方法再定义为final类型。

final修饰的类不可以被继承

class Dad{
        public final void turnOnTheTV() {
            System.out.println("爸爸打开了电视");
        }
    }
    class Baby extends Dad{
        public final void turnOnTheTV() {
            System.out.println("宝宝也要打开电视");
        }
    }


3.final类

定义为final 的类不能继承。如果希望一个类不被任何类继承,并且不允许其他人对这个类进任何改动,可以将这个类设置为final类。final类的语法如下:
final 类名
如果将某个类设置为final类,该类中的所有方法都被隐式设置为final法,但是final类成员变量可以被定义为final或非final形式。
例如,已知JDK中的java.lang包下的Math 数学类和String字符串类都是由 final关键字修饰的类这两个类就无法做任何类的父类,如果这两个类出现在extends右侧就会发生编译错误,

 class MyMath extends java.lang.Math{}
类型MyMath 不能成为终态类Math的子类
class MyString extends java.lang.String{}5
类型 MyString不能成为修态类 String的子类

七:多态
利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。在7.3已经习过子类对象可以作为父类的对象实例使用,这种将子类对象视为父类对象的做法称为“向上转型”
假如现在要编写一个绘制图形的方法draw(),如果传入正方形对象就绘制正方形,如果传入圆形对象就绘制圆形,这种场景可以使用重载来实现,定义如下:

public void draw(Square s){ //绘制正方形的方法 

}
public void draw(Circular c){ //绘制圆形的方法 

}

但是这种写法有个问题:正方形和圆形都是图形,这场景细分的重载方式不仅增加了代码量,还降低了“易用度”。如果定义一个图形类,让它处理所有继承该类的对象,根据“向上转型”原则可以使每个继承图形类的对象作为draw方法的参数,然后在draw方法中做一些限定就可以根据不同形类对象绘制相应的图形。这样处理能够很好地解决代码冗余问题,同时程序也易于维护。

class Shape{}//创建一个图形类
class Square extends Shape{}//正方形类继承图形类
class Circular extends Shape{}//圆形类继承图形类
public class winner {
    public static void draw(Shape s) {//绘制方法
        if(s instanceof Square) {//如果是正方形
            System.out.println("绘制正方形");//输出语句
        }else if(s instanceof Circular) {//如果是圆形
            System.out.println("绘制圆形");//输出语句
        }else {//如果是其他图形
            System.out.println("绘制父类图形");//输出语句
        }
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        draw(new Shape());//调用draw方法输出结果
        draw(new Square());
        draw(new Circular());
    }
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值