当前位置: 首页 > news >正文

大学生入门:抽象 及 接口

目录

一、抽象

1、抽象方法

2、抽象类

二、接口

1、概念

2、注意:

3、命名习惯

三、抽象类和接口对比

四、易踩坑的点 

1、抽象类

2、接口 

3、设计选择误区

在介绍抽象和接口之前,我们先来简单了解一下它们的历史背景和发展:

        java诞生时,抽象类其实是C++的“私生子”

        它继承了父类 virtual 函数特性,去掉了危险的 多重继承

        Sun 公司的工程师们当时喝着咖啡讨论着要不要让接口也能带方法体

        最终投票结果是:接口必须保持纯洁!

        

        (但是这个决定在20年后被推翻)

一、抽象

        抽象是将复杂的概念和现实问题简化为更易于理解和处理的表示方法

        在编程过程中,抽象关注问题的本质和关键特征,忽略其具体实现细节的方法

        在面向对象编程中,抽象主要通过定义类、接口和方法来实现

1、抽象方法

        将子类共性的行为(方法)抽取到父类中

        发现父类中无法实现子类的具体实现逻辑

        那么就可以将该方法定义为抽象方法

回顾一下普通方法:

大学生入门:初识方法及其易踩坑的点-CSDN博客https://blog.csdn.net/qq_73698057/article/details/149579229?spm=1011.2124.3001.6209

——特点:

        1> 无方法体

                只有方法声明

                没有具体的实现代码

        2> 必须在抽象类或者接口中

        3> 子类必须实现

        4> 不能是private、static、final修饰的

大学生入门:static及其易踩坑的点-CSDN博客https://blog.csdn.net/qq_73698057/article/details/149784774?spm=1011.2124.3001.6209

大学生入门:final 关键字-CSDN博客https://blog.csdn.net/qq_73698057/article/details/149944359?sharetype=blogdetail&sharerId=149944359&sharerefer=PC&sharesource=qq_73698057&spm=1011.2480.3001.8118

2、抽象类

用 abstract 关键字声明的类

——特点:

        1> 抽象类不能实例化创建对象

        2> 抽象类可以定义成员属性

        3> 包含抽象方法的类必须声明为抽象类

             没有抽象方法也可以声明为抽象类

        4> 子类必须重写父类中的所有抽象方法

                否则子类中会有隐藏的未重写的抽象方法

                此时子类需要声明为抽象类

                但是这样就违背了我们的初衷

                所以一定不要漏掉每一个抽象方法

        5> 含有构造器

                否则子类构造器super不到父类的构造方法

                没有显示提供的话,编译器会自动提供无参构造器

        6> 可以包含具体方法

// 抽象类定义
abstract class Animal {// 抽象类可以定义成员属性protected String name;protected int age;// 构造器(可选,但建议提供)public Animal() {this.name = "未知";this.age = 0;}public Animal(String name, int age) {this.name = name;this.age = age;}// 抽象方法(子类必须实现)public abstract void makeSound();// 具体方法(有实现)public void sleep() {System.out.println(name + " is sleeping");}// 普通具体方法public void eat() {System.out.println(name + " is eating");}// getter方法public String getName() {return name;}public int getAge() {return age;}
}// 具体子类 - 必须实现所有抽象方法
class Dog extends Animal {public Dog() {super(); // 调用父类构造器}public Dog(String name, int age) {super(name, age);}// 实现抽象方法@Overridepublic void makeSound() {System.out.println(name + " says: Woof!");}// 可以添加自己的方法public void wagTail() {System.out.println(name + " is wagging tail");}
}// 另一个具体子类
class Cat extends Animal {public Cat(String name, int age) {super(name, age);}@Overridepublic void makeSound() {System.out.println(name + " says: Meow!");}
}// 演示类
public class AbstractDemo {public static void main(String[] args) {// 抽象类不能直接实例化// Animal animal = new Animal(); // 编译错误// 创建具体子类对象Dog dog = new Dog("旺财", 3);Cat cat = new Cat("咪咪", 2);// 使用对象System.out.println("狗的名字:" + dog.getName() + ",年龄:" + dog.getAge());dog.makeSound();  // 实现的抽象方法dog.sleep();      // 继承的具体方法dog.wagTail();    // 自己的方法System.out.println();System.out.println("猫的名字:" + cat.getName() + ",年龄:" + cat.getAge());cat.makeSound();  // 实现的抽象方法cat.sleep();      // 继承的具体方法// 多态使用Animal animal1 = new Dog("小白", 1);Animal animal2 = new Cat("小花", 2);animal1.makeSound();animal2.makeSound();}
}

二、接口

1、概念

        1> 引用数据类型的一种

        2> java 是单继承,接口是对单继承的补充

                继承(父亲)亲爹唯一

                接口(老师)老师多个

        3> 关键字 implements

                可以和继承混合使用

                eg:

public class Dog extends Animal implements IAction1,IAction2{...
}

2、注意:

        1>

        接口关键字                        interface

        类关键字                            class

        类编译后文件后缀             .class

        接口编译后文件后缀          .class

        2> 接口不是类

                但是接口和类的实现关系中,可以使用多态

大学生入门:封装、继承和多态-CSDN博客https://blog.csdn.net/qq_73698057/article/details/149912534?spm=1001.2014.3001.5502                一个类可以同时实现多个接口

        3> 接口中的属性默认是常量,默认public static final修饰

             接口中的方法默认是抽象方法,默认public abstract修饰

             所以接口也不能实例化创建对象

        4> java中类的继承只能是单继承,不支持多继承

             java中类和接口之间的实现关系是多实现

             java中接口和接口之间的继承关系是多继承

        5> jdk8 之前,接口中只允许存在常量、抽象方法

             jdk8 引入 default 方法 和 static 方法(可以具体实现)

             jdk9 引入 private 方法 和 private static 方法(可以具体实现)

3、命名习惯

        类:首字母大写,驼峰命名

        接口:首字母一般是大写 I ,然后和类一样

接口综合示例:

// 定义一个接口 - Flyable(可飞行的)
interface Flyable {// 接口中的属性默认是 public static final 常量int MAX_ALTITUDE = 10000;// 接口中的方法默认是 public abstract 抽象方法void fly();void land();// 获取最大飞行高度int getMaxAltitude();
}// 定义另一个接口 - Swimmable(可游泳的)
interface Swimmable {// 抽象方法void swim();// 默认方法(JDK 8+)default void dive() {System.out.println("潜水ing...");}
}// 定义第三个接口 - Runnable(可奔跑的)
interface Runnable {void run();// 静态方法(JDK 8+)static void showSpeedInfo() {System.out.println("奔跑速度信息:哺乳动物通常奔跑速度在5-100km/h之间");}
}// 具体实现类 - 鸭子(实现了多个接口)
class Duck implements Flyable, Swimmable, Runnable {private String name;public Duck(String name) {this.name = name;}// 实现 Flyable 接口的方法@Overridepublic void fly() {System.out.println(name + " 正在天空中飞翔");}@Overridepublic void land() {System.out.println(name + " 安全着陆了");}@Overridepublic int getMaxAltitude() {return MAX_ALTITUDE; // 使用接口常量}// 实现 Swimmable 接口的方法@Overridepublic void swim() {System.out.println(name + " 正在水中游泳");}// 实现 Runnable 接口的方法@Overridepublic void run() {System.out.println(name + " 正在陆地上奔跑");}// 可以重写默认方法(可选)@Overridepublic void dive() {System.out.println(name + " 正在水中潜水觅食");}
}// 另一个实现类 - 人类
class Human implements Swimmable, Runnable {private String name;public Human(String name) {this.name = name;}@Overridepublic void swim() {System.out.println(name + " 正在游泳池里游泳");}@Overridepublic void run() {System.out.println(name + " 正在跑道上奔跑");}
}// 测试类
public class InterfaceDemo {public static void main(String[] args) {// 接口不能直接实例化// Flyable flyable = new Flyable(); // 错误!// 创建具体实现类对象Duck duck = new Duck("唐老鸭");Human human = new Human("小明");// 使用对象调用方法System.out.println("=== 鸭子的能力 ===");duck.fly();duck.land();System.out.println("最大飞行高度:" + duck.getMaxAltitude());duck.swim();duck.run();duck.dive(); // 调用默认方法System.out.println("\n=== 人类的能力 ===");human.swim();human.run();human.dive(); // 调用默认方法// 多态使用System.out.println("\n=== 多态演示 ===");Flyable flyable = new Duck("多态鸭子");Swimmable swimmable1 = new Duck("多态鸭子");Swimmable swimmable2 = new Human("多态人类");Runnable runnable1 = new Duck("多态鸭子");Runnable runnable2 = new Human("多态人类");flyable.fly();swimmable1.swim();swimmable2.swim();runnable1.run();runnable2.run();// 调用静态方法System.out.println("\n=== 静态方法调用 ===");Runnable.showSpeedInfo();}
}

三、抽象类和接口对比

维度抽象类接口
实例化不能直接实例化不能实例化
构造器必须存在不允许存在
方法实现可包含具体实现Java8前必须全部抽象
成员变量普通变量/常量均可只能是常量
设计目标代码复用+部分约束纯行为契约

四、易踩坑的点 

1、抽象类

1> 忘记定义构造器导致子类编译错误

2> 子类漏实现抽象方法却不声明 abstract

3> 错误实例化

//错误:
抽象类名 对象名 = new 抽象类名();//正确(使用多态的向上转型):
抽象类名 对象名 = new 子类名();

2、接口 

1> 常量被 final 修饰,不可修改

2> 实现多个接口时,出现同名默认方法冲突

interface A {default void method() {System.out.println("A's method");}
}interface B {default void method() {System.out.println("B's method");}
}// 错误 - 必须明确指定使用哪个接口的实现
/*
class C implements A, B {// 编译错误:类C从类型A和B继承了method()的不相关默认值
}
*/// 正确 - 重写冲突的方法
class C implements A, B {@Overridepublic void method() {A.super.method(); // 调用A的实现// 或者提供自己的实现}
}

3、设计选择误区

1> 过度使用抽象类导致继承体系臃肿

2> 用接口替代所有抽象场景(虽然要优先接口,但是需合理选择)

3> 混淆 extends 和 implements 关键字

http://www.dtcms.com/a/316371.html

相关文章:

  • 零基础人工智能学习规划之路
  • Python基础框架
  • MyBatis基础入门:Java持久层框架的技术深度解析
  • 脚手架开发-准备配置-配置文件的准备项目的一些中间件
  • Vue3 defineAsyncComponent() 函数
  • 客流人数统计准确率↑32%:陌讯多模态时序融合算法实战解析
  • 10.Linux 系统启动原理
  • 12306旅游产品数据抓取:Python+API逆向分析
  • 如何让 RAG 检索更高效?——大模型召回策略全解
  • 跨越系统孤岛:4A架构如何实现企业级一体化协同
  • 从RNN为什么长依赖遗忘到注意力机制的解决方案以及并行
  • chromedp 笔记
  • 同向双指针——滑动窗口
  • 使用公众号的消息模板给关注用户发消息
  • UNet改进(30):SageAttention在UNet中的4-Bit量化实现详解
  • UOS20操作系统关闭NUMA和透明大页(UOS20+KunPeng920)
  • mq_timedreceive系统调用及示例
  • 工业设备远程监控的 “颠覆性突破”:边缘计算网关让千里之外如在眼前
  • 【图像算法 - 09】基于深度学习的烟雾检测:从算法原理到工程实现,完整实战指南
  • 16核32G硬件服务器租用需要多少钱
  • 【Redis初阶】------单线程模型
  • Next.js SSR 实战:构建高性能新闻网站
  • C++中的泛型算法(三)
  • 智慧城市SaaS平台|市容环卫管理系统
  • 【PHP】对数据库操作:获取数据表,导出数据结构,根据条件生成SQL语句,根据条件导出SQL文件
  • nordic通过j-link rtt viewer打印日志
  • Unknown initial character set index ‘255’,Kettle连接MySQL数据库常见错误及解决方案大全
  • 心念之球:在意识的天空下
  • Gemini CLI最近更新
  • GitLab:一站式 DevOps 平台的全方位解析