9.接口、多态与继承

9.接口、继承与duo’t

继承,复用已定义的类,减少重复代码的编写

多态,动态调整对象的调用,降低对象之间依存关系

接口,优化继承和多态,建立类和类之间关联的标准

9.1继承

基于父类制造出一个新的子类,子类可以继承父类原有的属性和方法,增加原来父类不具有的属性和方法,或者直接重写父类中某些方法

举例1:

public class Text {

    public Text() {
        //构造方法
    }

    protected void doSomeThing() {
        System.out.println("调用Text().doSomeThing()");
    }

    protected Text doll() {
        System.out.println("返回Text()类型");
        return new Text();
        //返回类类型的成员函数
    }

    public static void main(String[] args) {
        //一个类文件中有多个类时,主函数应该在与类文件名相同的类中,否则需要自行指明主函数位置
        new Text2().doll();
        //子类可以直接调用父类的非privated方法
    }
}

class Text2 extends Text {
    //extends关键字用来继承父类
    public Text2() {
        super();
        //supper():可以调用父类构造方法,根据父类构造方法是否有参数再携带参数
        super.doSomeThing();
        //super关键字可以调用父类的非private方法
    }

    protected void doSomeThing() {
        // 重写构造方法
        System.out.println("Text调用函数dosomething");
    }

    public void doSomeThingNew() {
        // 新增成员方法
    }

    protected Text2 doll2() {
        // 重写返回类类型的父类方法
        return new Text2();
    }

}

要点:

1.extends()关键字用来声明继承关系,子类利用super()关键字调用父类方法

2.子类方法可以直接调用父类非private方法

3.重写父类方法,可以在子类中修改方法内容,更改方法存储权限,修改方法返回类型(J2SE5.0以上提供,重写后的返回值类型必须是父类中同名方法返回值类型的子类)

4.重构,特殊的重写方式,父类与子类方法返回值、方法名、参数表完全相同,方法实现内容不同

5.重写时,修改方法的修饰权限只能从小范围到大范围,不能降低方法修饰权限范围

举例2:

class Parent {
    Parent() {
        System.out.println("调用Parent()构造方法");
    }
}

class SubParent extends Parent {
    SubParent() {
        System.out.println("调用SubParent()构造方法");
    }
}

public class Subroutine extends SubParent {
    Subroutine() {
        System.out.println("调用Subroutine()构造方法");
    }

    public static void main(String[] args) {
        new Subroutine();
    }
}

要点:

1.实例化子类对象时,首先要实例化父类对象,java编辑器会在子类构造方法中自动调用父类无参数构造方法

2.若想在子类构造方法中调用父类有参构造方法,只能依赖于super关键字显式调用

3.如果使用finalize()方法清理对象,确保finalize()最后一个动作是调用父类的finalize()方法,否则部分对象不能被正常终止

9.2Object类

Object类是所有类的父类,Java类层最高层类,自定义类也继承自Object类,所以在定义类时,省略了extends Object关键字

Object类中有很多方法,如clone()、finalize()、equals()、toString()等,任何类都可以重写Object类中的方法,但getClass()、notify()、notifyAll()、wait()等被定义为final类型的方法除外

1.getClass()方法

该方法将返回对象执行时的Class实例,可以通过此实例调用getName()方法获得类名称,语法为:getClass().getName()

可以将getClass()放在重写的toString()方法中使用

2.toString()方法

该方法将一个对象以字符串的形式返回。实际应用中通常重写toString()方法,修改输出内容,当该类转换为字符串或者与字符串连接时,将自动调用重写的toString()方法。

public class ObjectInstance {
    public String toString() {
        //重写toString()方法
        return "在 " + getClass().getName() + " 类中重写toString()方法";
    }

    public static void main(String[] args) {
        System.out.println(new ObjectInstance());
        //打印该类对象时将自动调用toString()方法
    }
}

3.equals()方法

注意equals()和”==”的区别。

在基本数据类型中,equals()是比较两个对象实际内容是否相同,而”==”是比较两个对象的引用是否相等

在自定义类中,equals()默认实现方法是调用”==”比较两个两个对象引用地址是否相同,若想要比较两个自定义对象内容,需要重写equals()

class V {
    String abc;

    V(String abc) {
        this.abc = abc;
    }
}

class OverWriteEquals {
    public static void main(String[] args) {
        String s1 = "123";
        String s2 = "123";
        System.out.println(s1.equals(s2));
        V v1 = new V("123");
        V v2 = new V("123");
        System.out.println(v1.equals(v2));
    }
}

9.3对象类型的转换

9.3.1向上转型

把子类对象转换为父类对象,进行操作,这是一个由具体类到简单类的转换,安全

举例如下:

class Quadrangle {
    // 四边形类

    public static void draw(Quadrangle q) {
        // dosomeThing
    }
}

public class Parallelogram extends Quadrangle {
    // 平行四边形类,继承自四边形类
    public static void main(String[] args) {
        Parallelogram q = new Parallelogram();
        draw(q);
        /*
         * 子类对象转换为父类对象,作为参数,调用父类方法,相当于:
         *  Quadrangle q=new Parallelogram(); 
         * draw(q);
         */
    }
}

如果在父类方法中根据不同的子类设置不同处理,可以在父类中定义一个方法完成各个功能,这就是多态的基本思想

9.3.2向下转型

向下转型是将具体类转换成抽象类,必须显示、强制转换(告知编译器)

class Quadrangle {
    // 四边形类

    public static void draw(Quadrangle q) {
        // dosomeThing
    }
}

public class Parallelogram extends Quadrangle {
    // 平行四边形类,继承自四边形类
    public static void main(String[] args) {
        draw(new Parallelogram());
        // 向上转换,安全,相当于:
        Quadrangle q = new Parallelogram();
        // 该语句相当于,父类是子类
        /*
         * 错误举例1:
         *  Parallelogram p=q;
         *  该语句相当于说,子类是父类,即四边形是平行四边形,显然不正确,所以要强制转换如下:
         */
        Quadrangle p = (Quadrangle) q;
        /*
         * 错误举例2:
         *  Parallelogram p=new Quadrangle(); 
         * 错误原因相同,修改如下:
         */
        Parallelogram s = (Parallelogram) new Quadrangle();

    }
}

9.4instanceof判断对象类型

向下转型操作时,如果父类对象不是子类对象实例,就会发生ClassCastException异常,所以在向下转型之前用instanceof操作符检查,语法如下:

myobject instanceof ExampleClass

该表达式返回一个布尔值,myobject是每个对象的引用,ExampleClass是某个类

举例如下:

class Quadrangle{
    public static void draw(Quadrangle q){
        //SomeSentence
    }

}

class Square extends Quadrangle{
    //SomeSentence
}
class Anything{
    //SomeSentence
}


public class Parallelogram extends Quadrangle{

    public static void main(String[] args) {
        Quadrangle q =new Quadrangle();
        if(q instanceof Parallelogram){
            Parallelogram p=(Parallelogram)q;
        }
        if(q instanceof Square){
            Square s=(Square)q;
        }
//        q对象不为Anything类的对象,该语句错误
//        System.out.println(q instanceof Anything);

    }
}

当被测类为对象的父类实例、实例、子类实例时,均返回true

9.5重载

重载是指不同的方法使用相同的方法名

重载依照方法中参数表的参数类型、参数个数、参数顺序的不同,区分不同方法

主函数调用重载函数时仅提供参数表,不涉及返回类型,因此仅仅返回值不同不足以区分两个方法的重载

举例如下:

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(double a, int b) {
        return 1;
    }

    public static int add(int a, double b) {
        return 2;
    }

    public static void main(String[] args) {
        System.out.println(add(1, 2));
        System.out.println(add(1.2, 3.4));
        System.out.println(add(1, 2.3));
        System.out.println(add(2.3, 1));
    }

}

不定长参数方法,在方法中可以接受不确定个数的参数,可配合重载使用,语法如下:

返回值 方法名(参数数据类型 … 参数名)

此时,该不定长参数被视为一个数组,举例如下:

public class OverLoadTest2 {
    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(double a, int b) {
        return 1;
    }

    public static int add(int a, double b) {
        return 2;
    }
    public static int add(int...a){
        int s=0;
        for(int i=0;i<a.length;i++)
            s+=a[i];
        System.out.print("调用不等长参数方法:");
        return s;

    }


    public static void main(String[] args) {
        System.out.println(add(1, 2));
        System.out.println(add(1.2, 3.4));
        System.out.println(add(1, 2.3));
        System.out.println(add(2.3, 1));
        System.out.println(add(1,2,3,4,5,6));
        System.out.println(add(1));
    }

}

9.6多态

在父类方法中做出限定,根据调用时不同的子类对象,进行不同的处理
多态使程序具有更好的延展性,且避免了大量重复代码的开发
该思想依据是向上转型,即将子类对象当作父类对象处理
举例如下:

public class Quadrangle {
   private Quadrangle[] qtest=new Quadrangle[6];
   //被实例化的数组,用于保存四边形对象
   private int nextIndex=0;
   public void draw(Quadrangle q){
       //将参数对象加入数组,索引指向数组的下一位
       if(nextIndex<qtest.length){
           qtest[nextIndex]=q;
           System.out.println(nextIndex);
           nextIndex++;
       }
   }

    public static void main(String[] args) {
        Quadrangle q=new Quadrangle();
        //通过父类对象调用draw()方法
        q.draw(new Square());
        //qtest[0]指向该对象
        q.draw(new Parallelogramgle());
        //qtext[1]指向该对象
    }

}
class Square extends Quadrangle{
    public Square(){
        System.out.println("正方形");
    }
}
class Parallelogramgle extends Quadrangle{
    public  Parallelogramgle(){
        System.out.println("平行四边形");
    }
}

9.7抽象类和抽象方法

9.7.1抽象类

无法用语言描述的类,被称为抽象类,java抽象类不能实例化对象

在多态机制中,父类不需要初始化对象,故常常将父类定义为抽象类

关键字abstract定义了抽象类和抽象方法,举例如下:

public abstract class Test{
    abstract void testAbstract();
    //定义抽象方法,抽象方法无方法体
    //继承抽象方法时,要保证相同的方法名称、参数列表和返回值类型
}

抽象方法只能在抽象类中定义

抽象类和抽象方法除了被继承无任何意义

继承抽象方法时需要将抽象类中的全部抽象方法覆盖,带入太多冗余代码,此时需要用接口解决

9.7.2接口

1.接口简介

接口是抽象类的延伸,所有方法都没有方法体,可以看作是纯粹的抽象类。

接口中任意字段都是static和final的。

在接口中定义的方法必须被定义为public(默认, 不可修改)和abstract形式。其他修饰权限不被认可。

关键字interface用来定义接口,语法如下:

public interface drawTest{
    //public:接口的权限修饰符
    //drawTest:接口名称
    void draw();
    //接口内的方法,省略abstract关键字
}

一个类实现一个接口可以使用implements关键字,举例如下:

interface drawTest{   //定义接口
    public void draw();   //定义方法
}

//定义平行四边形类,该类继承四边形类,实现drawTest接口
class ParallelogramgleUseInterface extends QuadrangleUseInterface
implements drawTest{
    public void draw(){
        //该类实现了接口,需要覆盖接口内方法
        System.out.println("平行四边形.draw()");
    }
    public void doAnyThing(){
        //SomeSentence
        System.out.println();
    }
}

//定义正方形类,该类继承四边形类,实现drawTest接口
class SquareUseInterface extends QuadrangleUseInterface
implements drawTest{
    public void draw(){
        System.out.println("正方形.draw()");
    }
    public void doAnyThing(){
        //someSentence
    }
}

//定义四边形类
public class QuadrangleUseInterface{
    public void doAnyThing(){
        //SomeSentence
    }

    public static void main(String[] args) {
        drawTest[] d={  //接口进行向上转型操作
                new SquareUseInterface(),new ParallelogramgleUseInterface()};
        for(int i=0;i<d.length;i++){
            d[i].draw();
        }
    }
}

在java中,子类无论是向上转型为父类对象,还是向上转型为抽象父类对象,还是向上转型为该类实现接口,都是合法的

2.接口和继承

Java不允许一个类继承多个父类,但是允许一个类同时实现多个接口,多重继承可以用接口实现

用接口实现多重继承是需要实现接口中所有方法,可能产生庞大的代码量,多重继承语法如下:

class 类名 implements 接口1,接口2,...,接口n

定义接口时,可以使该接口继承另外一个接口

interface intf1{
}
interface intf2 extends intf1{
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值