首页 > 其他分享 >面向对象-接口和多态

面向对象-接口和多态

时间:2024-07-13 17:56:23浏览次数:11  
标签:子类 void 多态 接口 面向对象 父类 方法 public

 1.接口的特性:

  • 接口里的数据成员必须初始化,且数据成员均为常量;

  • 接口里的方法必须全部声明为 abstract ,也就是说,接口不能像抽象类一样保有一般的方法,而必须全部是“抽象方法”。

2.接口定义的语法:

interface 接口名称 // 定义抽象类
{
    final 数据类型 成员名称 = 常量; //数据成员必须赋初值
    
    abstract 返回值的数据类型 方法名称(参数...);
    //抽象方法,注意在抽象方法里,没有定义方法主体
}

接口与一般类一样,本身也具有数据成员与方法,但数据成员一定要赋初值,且此值将不能再更改,方法也必须是“抽象方法”。也正因为方法必须是抽象方法,而没有一般的方法,所以抽象方法声明的关键字 abstract 是可以省略的。

相同的情况也发生在数据成员身上,因数据成员必须赋初值,且此值不能再被更改,所以声明数据成员的关键字 final 也可省略。事实上只要记得:

  • 接口里的“抽象方法”只要做声明即可,而不用定义其处理的方式;

  • 数据成员必须赋初值。

既然接口里只有抽象方法,它只要声明而不用定义处理方式,于是自然可以联想到接口也没有办法像一般类一样,再用它来创建对象。利用接口打造新的类的过程,称之为接口的实现(implementation)。

3.接口实现的语法:

class 类名称 implements 接口A,接口B //接口的实现
{
    ...
}

简单来说,接口和抽象类很相似,不能实例化对象,需要用类去实现接口,重写抽象方法,并且需要实现这个接口中的所有抽象方法

 4.接口的扩展:

接口是 Java 实现多继承的一种机制,一个类只能继承一个父类,但如果需要一个类继承多个抽象方法的话,就明显无法实现,所以就出现了接口的概念。一个类只可以继承一个父类,但却可以实现多个接口。

接口与一般类一样,均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口,派生出的接口称为派生接口或子接口。通过这种机制,派生接口不仅可以保留父接口的成员,同时也可加入新的成员以满足实际的需要。

同样的,接口的扩展(或继承)也是通过关键字 extends 来实现的。有趣的是,一个接口可以继承多个接口,这点与类的继承有所不同。

接口扩展的语法:

interface 子接口名称 extends 父接口1,父接口2...
{
    ...
}
编程要求

5.接口的继承:

public interface IPrinter1 {
    default void print1(){
        System.out.println("黑白打印!");
    }
} 
public interface IPrinter2 {
    default void print2(){
        System.out.println("彩色打印!");
    }
} 
public interface IPrinter extends IPrinter1,IPrinter2  {
    default void print(){
        print1();
        print2();
    }
} 

6. 多态的条件:

  • 继承的存在(继承是多态的基础,没有继承就没有多态);

  • 子类重写父类的方法(多态下调用子类重写的方法);

  • 父类引用变量指向子类对象(子类到父类的类型转换)。

子类转换成父类时的规则:

  • 将一个父类的引用指向一个子类的对象,称为向上转型(upcasting),自动进行类型转换。此时通过父类引用调用的方法是子类覆盖或继承父类的方法,不是父类的方法。 此时通过父类引用变量无法调用子类特有的方法;

  • 如果父类要调用子类的特有方法就得将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,此时必须进行强制类型转换。

 例:

public class TestAnimalDemo {
    public static void main(String[] args) {
        show(new Cat()); // 以 Cat 对象调用 show 方法
        show(new Dog()); // 以 Dog 对象调用 show 方法
        Animal a = new Cat(); // 向上转型
        a.eat(); // 调用的是 Cat 的 eat
        Cat c = (Cat) a; // 向下转型
        c.work(); // 调用的是 Cat 的 work
    }
    public static void show(Animal a) {
        a.eat();
        // 类型判断
        if (a instanceof Cat) { // 猫做的事情
            Cat c = (Cat) a;
            c.work();
        } else if (a instanceof Dog) { // 狗做的事情
            Dog c = (Dog) a;
            c.work();
        }
    }
}
abstract class Animal {
    abstract void eat();
}
class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼");
    }
    public void work() {
        System.out.println("抓老鼠");
    }
}
class Dog extends Animal {
    public void eat() {
        System.out.println("吃骨头");
    }
    public void work() {
        System.out.println("看家");
    }
}

可以用 instanceof 判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类。instanceof 的语法格式为:

对象 instanceof 类(或接口)

7.多态的不同实现方式:

基于继承实现的多态

假设我们有一个父类 Animal 和两个子类 Dog 和 Cat,它们都继承自 Animal 并重写了 eat() 方法。

// 父类  
class Animal {  
    void eat() {  
        System.out.println("This animal eats food.");  
    }  
}  
  
// 子类 Dog  
class Dog extends Animal {  
    @Override  
    void eat() {  
        System.out.println("Dog eats meat.");  
    }  
}  
  
// 子类 Cat  
class Cat extends Animal {  
    @Override  
    void eat() {  
        System.out.println("Cat eats fish.");  
    }  
}  
  
// 测试类  
public class TestPolymorphism {  
    public static void main(String[] args) {  
        Animal myDog = new Dog();  
        Animal myCat = new Cat();  
  
        myDog.eat(); // 输出: Dog eats meat.  
        myCat.eat(); // 输出: Cat eats fish.  
  
        // 即便引用类型是Animal,实际执行的是子类重写后的方法  
    }  
}

在这个例子中,Animal 类型的引用 myDog 和 myCat 分别指向了 Dog 和 Cat 的实例。当调用 eat() 方法时,根据对象的实际类型(即运行时类型),Java虚拟机能够确定并执行对应子类中的方法。 

基于接口实现的多态 

 现在,我们定义一个接口 Eatable 和两个实现了该接口的类 Apple 和 Banana

// 接口  
interface Eatable {  
    void eat();  
}  
  
// 实现类 Apple  
class Apple implements Eatable {  
    @Override  
    public void eat() {  
        System.out.println("Eating an apple.");  
    }  
}  
  
// 实现类 Banana  
class Banana implements Eatable {  
    @Override  
    public void eat() {  
        System.out.println("Eating a banana.");  
    }  
}  
  
// 测试类  
public class TestPolymorphismInterface {  
    public static void main(String[] args) {  
        Eatable fruit1 = new Apple();  
        Eatable fruit2 = new Banana();  
  
        fruit1.eat(); // 输出: Eating an apple.  
        fruit2.eat(); // 输出: Eating a banana.  
  
        // 即便引用类型是Eatable,实际执行的是实现类中的方法  
    }  
}

在这个例子中,Eatable 类型的引用 fruit1 和 fruit2 分别指向了 Apple 和 Banana 的实例。同样地,当调用 eat() 方法时,Java虚拟机根据对象的实际类型来执行对应的方法。这种方式展示了接口如何提供一种灵活的方式来定义一组方法的集合,并由不同的类来实现这些方法,从而实现多态。

        从表面上看,基于继承和基于接口实现的多态在Java中有很多相似之处,尤其是在它们如何允许不同的类以不同的方式实现相同的方法签名方面。然而,它们之间还是存在一些关键的区别和用途上的差异。

继承与多态

  • 继承 是一种“is-a”关系,即子类是一个特殊的父类。当你通过继承来实现多态时,你通常是在处理一组具有共同特征和相关行为的类。
  • 多态 通过继承实现时,主要是通过子类重写父类的方法来体现的。不同的子类可以以不同的方式实现相同的方法,从而在同一接口下展现出不同的行为。
  • 继承允许子类继承父类的属性和方法,但同时也带来了耦合性较高的问题。如果父类发生变化,可能会影响到所有子类。

接口与多态

  • 接口 是一种“can-do”关系,它定义了一组方法规范,但不提供具体的实现。实现接口的类必须遵循这些方法规范并提供具体实现。
  • 多态 通过接口实现时,不同的类可以实现同一个接口,并各自提供接口中方法的实现。这使得在不知道具体实现类的情况下,可以编写通用的代码来操作实现了该接口的任何对象。
  • 接口提供了一种更加灵活和松耦合的方式来定义和实现多态。一个类可以实现多个接口,从而具有多种行为。此外,接口还可以被用作类型,允许在编译时进行类型检查,同时保持运行时的灵活性。

关键点总结

  • 继承 是为了代码复用和表达类之间的“is-a”关系。它允许子类继承父类的属性和方法,并通过重写来提供特定的实现。
  • 接口 是为了定义一组方法的规范,实现接口的类必须遵循这些规范。接口提供了一种更加灵活和松耦合的方式来定义和实现多态。
  • 多态 允许我们以统一的方式处理不同类型的对象,而无需关心它们的具体实现。无论是通过继承还是接口实现,多态都是面向对象编程中一个非常强大的特性。

8.向上转型和向下转型: 

 向上转型

把子类对象赋值给父类类型的变量(隐式转换,不用进行强制类型转换),被称为向上转型。

本质:父类的引用指向了子类的对象。

语法:父类类型 引用名 = new 子类类型();

class Animal{
    public void info(){
        System.out.println("我是动物");
    }
}
class Dog extends Animal{
    public void eat(){
        System.out.println("狗在吃东西");
    }
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        animal.info();
    }
}

狗对象可以调用该方法,那么同样猫也可以调用该方法,这就做到了在父类中定义一个方法可以完成各个子类的功能。由于向上转型是一个从较具体类到较抽象类的转换,所以它总是安全的,因为我们可以说狗是动物,但是不能说动物是狗。

向上转型的特点如下:

  • 向上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能使用子类新增的方法(失掉了一些功能);

  • 向上转型对象可以操作子类继承或重写的成员变量,也可以使用子类继承的或重写的方法;

  • 如果子类重写了父类的某个方法后,当对象的向上转型对象调用这个方法时一定是调用了这个重写的方法,因为程序在运行时知道,这个向上转型对象的实体是子类创建的,只不过损失了一些功能而已。

向下转型

向下转型是指子类引用父类对象,就是将父类对象能转换成子类对象,这时需要满足两个条件:一是必须执行强制类型转换;二是必须确保父类对象是子类的一个实例,否则抛出异常。

语法:子类类型 引用名 = (子类类型)父类引用;

class Animal{
    public void info(){
        System.out.println("我是动物");
    }
}
class Dog extends Animal{
    public void eat(){
        System.out.println("狗在吃东西");
    }
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        Dog animal1 = (Dog) animal; // 向下转型
        animal1.eat();
    }
}

 向下转型的特点如下:

  • 向下转型对象可以操作父类及子类成员变量和成员方法;

  • 向下转型对象访问重写父类的方法时,操作的是子类的方法;

  • 向下转型必须进行强制类型转换;

  • 向下转型必须保证父类对象引用的是该子类的对象,如果引用的是父类的其他子类对象,会抛出类型不匹配异常。

标签:子类,void,多态,接口,面向对象,父类,方法,public
From: https://blog.csdn.net/Nuyoah6666/article/details/140354074

相关文章

  • Java中的接口多继承详解
    Java中的接口多继承详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java中,类的多继承是不被允许的,但是接口的多继承却是被允许的。接口多继承可以使得类具备多种行为,并且解耦合代码,有助于提升代码的可维护性和可扩展性。本文将详细介绍Java中接口多......
  • 全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则
    全网最适合入门的面向对象编程教程:16类和对象的Python实现-多态、方法重写与开闭原则摘要:本文主要介绍了Python中创建自定义类时子类如何实现对父类方法的重写、方法重写的定义和多态的基本概念,并对开闭原则进行介绍。原文链接:FreakStudio的博客往期推荐:学嵌入式的你,......
  • 关于面向对象的方法并行执行的问题
    LabVIEW的从同一个类实例化的多个对象如何执行各自的方法呢?这几天跟同事讨论到LabVIEW的面向对象编程中,如果我设计的一个类有一个方法比较耗时,那么当我实例化多个对象时,那么这个耗时的方法是怎么执行的呢?是各自并行执行还是,必须等某一个对象的方法调用完,接下来调用第二个对象的该......
  • 8-Map接口和常用方法
    8-Map接口和常用方法Map与Collection并列存在。用于保存具有映射关系的数据:Key-ValueMap中的key和value可以是任何引用数据类型,会封装到HashMap$Node对象中Map中的key不允许重复Map中的value可以重复Map的key可以为null,value也可以为null,注意key......
  • 【python学习】面向对象编程以及面向对象编程的核心概念和使用方法
    引言Python语言设计之初,就是为了面向对象,所以Python的面向对象更加易于理解。面向对象编程中,我们将现实世界的实体视为对象,每个对象都有属性(数据)和行为(方法)文章目录引言一、面向对象编程是什么二、面向过程编程和面向对象编程的区别2.1面对过程编程2.2面向对象编......
  • C++中的多态
    抽象类概念在虚函数的后面写上=0,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。......
  • Java三剑客:封装、继承、多态的魔法世界
    第一章:封装的艺术——保护你的宝藏案例分析:银行账户系统想象一下,你正在构建一个银行账户系统。每个账户都有一个余额,这个余额需要受到严格的保护,不能被随意修改。我们可以通过封装来实现这一目标。示例代码:publicclassBankAccount{privatedoublebalance;//......
  • Avalon MM 接口的PIO的bidir和inout的区别
     当我们设置PIO这个IP的方向的时候,可以看到: Input和Output一个是输入,一个是输出,那么Bidir和InOut有什么区别呢? bidir,指n位宽的信号中的每1bit,可以单独分别设置为读还是写。inout,指将n位宽的信号,全设置为读或写。只有设置为bir模式的时候,才存在direction寄存器,用于控制......
  • WSDL接口调用
    1.使用ApacheCXF工具调用1.1.MAVEN引用<!--cxf--><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.1.10</version></dependency><depen......
  • 推荐几个免费的http mock接口
    在前后端分离开发架构下,经常遇到调用后端数据API接口进行测试、集成、联调等需求,比如:(1)前端开发人员很快开发完成了UI界面,但后端开发人员的API接口还没有完成,不能进行前后端数据接口对接和联调,很容易影响开发进度。前端开发人员用的比较多的开源组件有mock.js,但该组件缺乏界面管理......