java类和对象:继承、多态、接口、抽象类-2

简介: java类和对象:继承、多态、接口、抽象类

java类和对象:继承、多态、接口、抽象类-1

https://developer.aliyun.com/article/1515765


二、多态

          对于几个不同的类,可以根据他们共同特性,将其抽取出来形成一个共同的父类,这个父类中包含了其他类所具有的共同属性,例如这里有一个狗类,一个猫类,和一个鸟类,他们都有眼睛,都有脚,还可以拥有自己的名字等等静态属性,动态属性,就比如都会吃,喝跑等。


       但是对于不同的动物来说,比如狗和鸟,他们的跑这个行为是不一样的,对于狗来说是用四条腿来跑,而对于鸟来说,只能用两个脚跳,或者用两个翅膀飞,这个行为和狗对比起来是完全不一样的,那么对于其继承的父类来说,不可能只用父类的方法,来描述两个不同的行为,这些行为都是他们的独自的特性。


       这个时候就只需要对其父类的这个方法于子类中进行重写,而不用在每一个子类都实现一个方法,于是就避免了大量重复的代码的编写。同时只需要实例化一个继承这个父类的子类对象,即可调佣相应的方法。

class Animal{
    public void action(){
        System.out.println("正在跑");
    }
}
class Dog extends Animal{
    public void action(){
        System.out.println("正在用四条腿跑");
    }
}
class Bird extends Animal{
    public void fly(){
        System.out.println("正在飞");
    }
}


例如这里有一个Animal父类,其中一个Dog类和Bird类继承这个Animal类。父类中有action这个方法,但是对于鸟和狗来说,他们的行为是不一样的,比如狗是用四条腿跑,而鸟是用翅膀飞。

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Bird bird = new Bird();
        dog.action();
        bird.action();
    }
}


结果如下:

三、抽象类


       有时候我们在实例化对象的时候,难免会将一个父类不小心给实例化了,但是有的情况是不允许父类被实例化的。例如一个父类Animal动物类,他被他的子类Dog继承。我们可以将Dog实例化成一个具体的dog,但是你并不能将一个动物给具体抽象出来,一个动物直接抽象出来会是什么?怎么归类?但是我们又只需要实例化子类对象,而不是父类对象。这就是一大麻烦,为了避免这个问题,我们需要将这个父类设置为抽象类,来避免父类被实例化。


       在实际解决问题的时候,通常将父类设置为抽象类,然后对这个父类进行继承和多态处理,继承关系中,越是在上方的类越抽象,例如狗类继承哺乳类,哺乳类继承动物类等。


       抽象类的语法如下:


public abstract class Test类名{        


       abstract void function( );


}


       abstract为定义抽象类关键字,使用abstract关键字定义的类为抽象类,而使用这个关键字定义的方法被称为抽象方法,这个方法不能有方法体,方法本身没有任何意义,它的作用只存在于被子类重写后。一个类如果有抽象方法,那么他必须被定义为抽象类(如果声明一个抽象方法,就必须将含有这个抽象方法的类定义为抽象类),实际上抽象类除了被继承之外没有任何意义,抽象类同时也保证了类在被继承的时候的安全性。


       对于继承这个抽象类的子类来说,子类需要重写这个抽象类中的所有的抽象方法。


四、接口类

       举一个很简单的例子,一个父类中存在属性:名字,年龄行为:跑,游泳(两个都是抽象方法);


然后我们定一个狗类(假设不会游泳),和一个鱼类都继承这个父类,那么对于狗类和鱼类来说都需要实现跑和游泳这两抽象方法,那么问题来了,狗如何去实现游泳这个方法?那么鱼又如何去实现跑这个方法?鱼不可能会跑,狗不能游泳,或者说狗类不用重写和实现这个方法,那么这个抽象方法是不可能被实现的,但是需要继承这个父类的名字和年龄等属性,为了应对这种问题,接口的概念就出现了。


       接口就是为了应对这种父类不能完全将子类中的共同特性抽取出来的情况。


语法如下:


关键字:interface


interface Test(接口名){


       void  function();  // 接口内的方法,省略abstract关键字。


}

使用implements 来让类实现该接口



在接口中,方法必须被定义为public或abstract的形式其他修饰限定符不被java编译器认可,即使该方法没有被public修饰,也是默认public权限,并且接口中被定义的任何字段都是自动被static和final修饰的。


实现某个接口的类,这个类就必须实现重写这个接口中的方法。

案例如下:

interface Fly{
    void fly();
}
interface Run{
    void run();
}
class Dog implements Run{
    @Override
    public void run() {
        System.out.println("dog is running");
    }
}
class Bird implements Fly{
    public void fly(){
        System.out.println( "bird is flying");
    }
}
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Bird bird = new Bird();
        dog.run();
        bird.fly();
    }
}


       结果如图

接口类型也可是实现向上转型

 

interface Run{
    void run();
}
class Dog implements Run{
    @Override
    public void run() {
        System.out.println("dog is running");
    }
}
public class Main {
    public static void main(String[] args) {
        Run run = new Dog();
        run.run();
    }
}


结果如下:

五、final关键字

重写和继承的功能很强大,但是必然也存在着不允许被重写或者继承的情况,这个时候就可以使用final修饰类或者方法,来防止某些不允许被重写和继承的情况。


1、final防止重写

       为了方法方法被重写,需要在方法声明的开始处将final指定为修饰符,被final修饰的方法不能被重修。

class A{
    final void method(){
        System.out.println("hello");
    }
}
class B extends A{
    void method(){
        System.out.println("hello java");
    }
}


报错如下:

2、使用final放置继承

在声明类的时候可以在开始的位置加上final关键字,以防止其被其他类继承:

final class A{
    // 方法体
}
class B extends A{
    // 方法体
}


执行后显示

85cf1c028f0e372308f360e7e6daa885_b8b699899e9748118352cf29ddfd3450.png

       如果一个类被abstract和final同时修饰,是非法的。如果这个类被abstract修饰,那么其中必定包含abstract方法,abstract方法必须被重写,但是被final修饰的类,其中的方法都是隐式的被final修饰,也就是说其中的所有方法都不能被重写,因此同时被final和abstract修饰是没有意义的,是不合法的。


3、final修饰的变量

final不仅可以修饰方法和类,还可以用来修饰成员变量,如果一个变量被final修饰,那么它的值在其生命周期内就不能改变。但是可以给他初始化。final修饰的变量初始化可以直接赋值,也可以使用代码块和构造方法来对其进行初始化,不管怎么样,必须对其选取这几种方法中的一个来初始化

初始化:

1、可以使用代码块

class A{
    final int a;
    {
        a = 10;
    }
}

如果这个变量同时被static修饰,那么可以使用static静态代码块来对其进行初始化:

1. class A{
2. final static int a;
3. static {
4.         a = 10;
5.     }
6. }

2、构造器初始化

class A{
    final  int a;
    public A(int a) {
        this.a = a;
    }
}


目录
相关文章
|
5月前
|
Java Go 开发工具
【Java】(9)抽象类、接口、内部的运用与作用分析,枚举类型的使用
抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接 口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类abstract static不能同时修饰一个方法。
285 1
|
9月前
|
安全 Java API
Java 抽象类与接口在 Java17 + 开发中的现代应用实践解析
《Java抽象类与接口核心技术解析》 摘要:本文全面剖析Java抽象类与接口的核心概念与技术差异。抽象类通过模板设计实现代码复用,支持具体方法与状态管理;接口则定义行为规范,实现多态支持。文章详细对比了两者在实例化、方法实现、继承机制等方面的区别,并提供了模板方法模式(抽象类)和策略模式(接口)的典型应用示例。特别指出Java8+新特性为接口带来的灵活性提升,包括默认方法和静态方法。最后给出最佳实践建议:优先使用接口定义行为规范,通过抽象类实现代码复用,合理组合两者构建灵活架构。
299 2
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
1239 60
|
11月前
|
Java 编译器 程序员
java中重载和多态的区别
本文详细解析了面向对象编程中多态与重载的概念及其关系。多态是OOP的核心,分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态主要通过方法重载和运算符重载实现,如Java中的同名方法因参数不同而区分;运行时多态则依赖继承和方法重写,通过父类引用调用子类方法实现。重载是多态的一种形式,专注于方法签名的多样性,提升代码可读性。两者结合增强了程序灵活性与扩展性,帮助开发者更好地实现代码复用。
616 0
|
Java
Java 面向对象编程的三大法宝:封装、继承与多态
本文介绍了Java面向对象编程中的三大核心概念:封装、继承和多态。
696 15
Java基础(13)抽象类、接口
本文介绍了Java面向对象编程中的抽象类和接口两个核心概念。抽象类不能被实例化,通常用于定义子类的通用方法和属性;接口则是完全抽象的类,允许声明一组方法但不实现它们。文章通过代码示例详细解析了抽象类和接口的定义及实现,并讨论了它们的区别和使用场景。
233 2
|
Java
Java——抽象类和接口
抽象类是一种不能被实例化的类,至少包含一个抽象方法(无实现体的方法),常用于定义一组相关类的共同特征,并强制子类实现特定方法。抽象方法不能被 `static` 或 `final` 修饰,且必须被重写。 接口则是一个完全抽象的类,用于规范类的行为。接口使用 `interface` 关键字定义,不能实例化,并且类与接口之间是实现关系。 内部类是在一个类内定义的类,分为成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类可被修饰符修饰,静态内部类只能访问外部类的静态成员,局部内部类定义在方法内,匿名内部类则隐藏了名字,直接通过 `new` 关键字定义并实现接口或继承类。
145 5
Java——抽象类和接口