JavaSE——面向对象10:抽象类、接口

news2024/11/25 22:48:19

目录

一、抽象类

(一)抽象类的引出

(二)抽象类基本介绍

(三)注意事项和使用细节

(四)抽象类的最佳实践——模板设计模式

二、接口

(一)接口快速入门

(二)基本介绍

(三)注意事项与使用细节

(四)接口VS继承

(五)接口的多态性

1.多态参数

2.多态数组

3.接口存在多态传递现象

(六)练习题


一、抽象类

(一)抽象类的引出

        当父类的某些方法,需要声明,但是又不确定如何实现时,就可以将其声明为抽象方法,那么这个就是抽象类。

class Animal{
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    // 这里的eat实现了没有什么意义
    // 即:父类方法的不确定性问题
    public void eat(){
        System.out.println("这时一只动物,但是不知道吃什么");
    }
}

        父类方法有不确定性,所以可以将该方法设计为抽象(abstract)方法,所谓抽象方法就是没有实现的方法,即没有方法体。

改写后的代码:

abstract class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }
    
    public abstract void eat();
}

        当父类的一些方法不确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类。即:当一个类中存在抽象方法时,需要将该类声明为abstract类。一般来说,抽象类会被继承,由其子类来实现抽象方法。

(二)抽象类基本介绍

  1. 用abstract关键字来修饰一个类时,这个类就叫抽象类
    访问修饰符 abstract 类名{
    }
  2. 用abstract关键字来修饰一个方法时,这个方法就是抽象方法
    访问修饰符 abstract 返回类型 方法名(参数列表); // 没有方法体
  3. 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类,在框架和设计模式中使用比较多

(三)注意事项和使用细节

  1. 抽象类不能被实例化
  2. 抽象类不一定要包含abstract方法,也就是说,抽象类可以没有abstract方法,还可以有实现的方法
  3. 一旦类包含了abstract方法,则这个类必须声明为abstract
  4. abstract只能修饰类和方法,不能修饰属性和其他的。
  5. 抽象类可以有任意成员(因为抽象类仍然是类),比如:非抽象方法、构造器、静态属性等等
    abstract class A {
        private String name;
        public static int age = 10;
        public static final int FEED_TIMES = 3;
        
        public A() {
            System.out.println("无参构造器");
        }
    
        public A(String name) {
            System.out.println("有参构造器");
            this.name = name;
        }
    
        public static void ok() {
            System.out.println("静态方法");
        }
    
        public void hello() {
            System.out.println("成员方法");
        }
    
        public abstract void m1();
    
        static {
            System.out.println("static代码块");
        }
    
        {
            System.out.println("普通代码块");
        }
    }
  6. 抽象方法不能有方法体
  7. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。
    ​
    abstract class E {
        public abstract void hi();
    }
    
    abstract class F extends E {
    
    }
    
    class G extends E {
        /**
         * 这里相当于子类G实现了父类E的抽象方法,
         * 所谓实现方法,就是有方法体
         */
        @Override
        public void hi() {
    
        }
    }
  8. 抽象方法不能使用private、final和static来修饰,因为这些关键字都是和重写相违背的。

(四)抽象类的最佳实践——模板设计模式

        模板设计模式(Template Method Pattern)是一种行为型设计模式,它定义了一个操作中的算法骨架,而将一些步骤的实现延迟到子类中。

        例如子类AA和子类BB中都有job方法,想要查看每个类的job方法的运行时间,就需要在每个job方法中进行时间差的计算,会造成代码重复,将计算时间差的重复代码抽取到父类中,形成一个模板,并且父类定义job的抽象方法,模板中调用job抽象方法。

        此时子类可以先重写各自的job方法,在main方法中调用模板即可,根据Java的动态绑定机制,哪个对象调用模板,最后就运行哪个对象的job方法。

public class TestTemplate {
    public static void main(String[] args) {
        AA aa = new AA();
        aa.calculateTime(); // 执行时间:4

        BB bb = new BB();
        bb.calculateTime(); // 执行时间:7
    }
}

abstract class Template {
    // 抽象方法
    public abstract void job();

    // 普通父类方法,调用抽象方法
    // 下面的方法时一个模板,可以用final修饰,防止被其他类重写
    public final void calculateTime() {
        long start = System.currentTimeMillis();
        job(); // 动态绑定机制,子类可以自定义job方法的内部逻辑
        long end = System.currentTimeMillis();
        System.out.println("执行时间:" + (end - start));
    }
}

class AA extends Template {

    @Override
    public void job() {
        long sum = 0;
        for (long i = 1; i <= 8000000; i++) {
            sum += i;
        }
    }
}

class BB extends Template {

    @Override
    public void job() {
        long sum = 0;
        for (long i = 1; i <= 8000000; i++) {
            sum *= i;
        }
    }
}

二、接口

(一)接口快速入门

        现实生活中我们常说的接口例如USB接口,你可以把手机、相机、U盘都插在USB插槽上,而不用担心哪个插槽是专门插哪个的,原因是做USB插槽的厂家,和做各种设备的厂家都遵守了同意的规定,包括尺寸、排线等等。

        下面我们先看用代码实现接口的案例:

首先定义一个USB接口:

public interface UsbInterface { //接口
    //规定接口的相关方法
    public void start();
    public void stop();
}

再定义一个Phone类,实现这个接口,并实现接口中的全部方法:

// 即 Phone类需要实现 UsbInterface接口 规定/声明的方法
public class Phone implements UsbInterface {

    @Override
    public void start() {
        System.out.println("手机开始工作...");
    }

    @Override
    public void stop() {
        System.out.println("手机停止工作.....");
    }
}

再定义一个Camera类,也实现这个接口,并实现接口中的全部方法:

public class Camera implements UsbInterface {
    // 实现接口,就是把接口方法实现

    @Override
    public void start() {
        System.out.println("相机开始工作...");
    }

    @Override
    public void stop() {
        System.out.println("相机停止工作....");
    }
}

定义一个Computer类,能够接收接口:

public class Computer {
    //编写一个方法, 计算机工作:
    //1. UsbInterface usbInterface 形参是接口类型 UsbInterface
    //2. 看到 接收 实现了 UsbInterface接口的类的对象实例
    public void work(UsbInterface usbInterface) {
        // 通过接口,来调用方法
        usbInterface.start();
        usbInterface.stop();
    }
}

main方法中创建对象运行:

public class Interface01 {
    public static void main(String[] args) {
        //创建手机,相机对象
        //Camera 实现了 UsbInterface
        Camera camera = new Camera();
        //Phone 实现了 UsbInterface
        Phone phone = new Phone();
        //创建计算机
        Computer computer = new Computer();
        computer.work(phone);// 把手机接入到计算机
        System.out.println("===============");
        computer.work(camera);// 把相机接入到计算机
    }
}

运行结果:

 

(二)基本介绍

        接口就是给出一些没有实现的方法,封装到一起,直到某个类要使用的时候,再根据具体情况把这些方法实现了、

基本语法:

interface 接口名{
    // 属性
    // 方法(1.抽象方法; 2.默认实现方法 3.静态方法)
}


class 类名 implements 接口{
    自己的属性;
    自己的方法;
    必须实现的接口的抽象方法;
}

小结:

  1. 在JDK7.0以前,接口里的所有方法都没有方法体,即都是抽象方法。
  2. JDK8.0及以后,接口类可以有静态方法、默认方法,也就是说,接口中可以有方法的具体实现。即(接口类中可以定义:1.抽象方法; 2.默认实现方法 3.静态方法)
    public interface AInterface {
        //属性:
        public int n1 = 10;
    
        // 方法:
        // 在接口中,抽象方法,可以省略abstract关键字
        public void hi();
    
        // 在jdk8后,接口中可以有默认实现方法,需要使用default关键字修饰
        default public void ok() {
            System.out.println("ok ...");
        }
    
        // 在jdk8后, 接口中可以有静态方法
        public static void cry() {
            System.out.println("cry ....");
        }
    }
    
    
    // 1.如果一个类 implements实现 接口
    // 2.需要将该接口的所有抽象方法都实现
    class A implements AInterface {
        @Override
        public void hi() {
            System.out.println("hi()....");
        }
    }

(三)注意事项与使用细节

  1. 接口不能被实例化

  2. 接口中所有的方法是 public方法,接口中抽象方法,可以不用abstract修饰

  3. 一个普通类实现接口,就必须将该接口的所有方法都实现,可以使用alt+enter来解决

  4. 抽象类去实现接口时,可以不实现接口的抽象方法

  5. 一个类同时可以实现多个接口:class Pig implements IB, IC {}

  6. 接口中的属性,只能是final的,而且是 public static final 修饰符,并且必须被初始化:

    interface IB {int n1 = 10;} // public static final 部分可以省略

  7. 接口中属性的访问形式:接口名.属性名

  8. 接口不能继承其它的类,但是可以继承多个别的接口:interface ID extends IB, IC {}

  9. 接口的修饰符 只能是 public 和默认,这点和类的修饰符是一样的:interface IE {}

public class InterfaceDetail01 {
    public static void main(String[] args) {
        // 1.接口不能被实例化
        // new IA();
    }
}

interface IA {
    // 2.接口中所有的方法是 public方法, 接口中抽象方法,可以不用abstract修饰
    void say();// 修饰符 public protected 默认 private
    // 相当于 public abstract void say();

    void hi();
}

// 3.一个普通类实现接口,就必须将该接口的所有方法都实现,可以使用alt+enter来解决
class Cat implements IA {
    @Override
    public void say() {
        System.out.println("实现接口IA的say方法");
    }

    @Override
    public void hi() {
        System.out.println("实现接口IA的hi方法");
    }
}

// 4.抽象类去实现接口时,可以不实现接口的抽象方法
abstract class Tiger implements IA {}
public class InterfaceDetail02 {
    public static void main(String[] args) {
        // 接口中的属性,是 public static final
        // 7.接口中属性的访问形式:接口名.属性名
        System.out.println(IB.n1);// 说明n1 就是static
        // IB.n1 = 30; // 无法重新赋值,说明n1是final
    }

}

interface IB {
    // 6.接口中的属性,只能是final的,而且是 public static final 修饰符,并且必须被初始化
    int n1 = 10; // 等价于 public static final int n1 = 10;

    void hi();
}

interface IC {
    void say();
}

// 5.一个类同时可以实现多个接口
class Pig implements IB, IC {
    @Override
    public void hi() {
        System.out.println("实现IB的hi方法");
    }

    @Override
    public void say() {
        System.out.println("实现IC的say方法");
    }
}

// 8.接口不能继承其它的类,但是可以继承多个别的接口
interface ID extends IB, IC {}

// 9.接口的修饰符 只能是 public 和默认,这点和类的修饰符是一样的
interface IE {}

小练习:分析下面代码是否有错误与输出结果:

public class InterfaceExercise01 {
    public static void main(String[] args) {
        B b = new B();//ok
        System.out.println(b.a);  //23  因为a是public,所以可以访问
        System.out.println(AA.a);  //23  因为a是static类型,所以可以直接调用
        System.out.println(B.a);  //23  因为B实现了AA接口,所以AA的属性和方法也能访问到
    }
}

interface AA {
    int a = 23; //等价 public static final int a = 23;
}

class B implements AA {//正确
}

(四)接口VS继承

  • 接口和继承解决的问题不同

        继承的价值主要在于:解决代码的复用性和可维护性。

        接口的价值主要在于:设计好各种规范(方法),让其它类去实现这些方法。

  • 接口比继承更加灵活

        继承是满足is-a的关系,比如Cat可以继承Animal,而Computer不能;

        接口只需满足like-a的关系,比如,通过实现接口中的方法,Cat也可以像Computer一样具有上网的功能。

  • 接口在一定程度上实现代码的解耦[即:接口规范性+动态绑定机制]
public class ExtendsVsInterface {
    public static void main(String[] args) {
        LittleMonkey littleMonkey = new LittleMonkey("悟空");
        // 子类可以调用父类的属性和方法
        littleMonkey.climbing(); // 悟空可以爬树...
        
        // 子类可以调用重写的接口方法
        littleMonkey.swimming(); // 悟空通过学习,可以像鱼儿一样游泳...
        littleMonkey.flying(); // 悟空通过学习,可以像鸟儿一样飞翔...
    }
}

// 如果LittleMonkey想要实现父类Monkey没有的功能,就需要实现对应的接口
// 定义接口Fishable
interface Fishable {
    // 编写接口中的抽象方法,swimming
    void swimming();
}

// 另一个接口Birdable
interface Birdable {
    void flying();
}

// 编写父类Monkey
class Monkey {
    private String name;

    public void climbing() {
        System.out.println(name + "可以爬树...");
    }

    public Monkey(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

// 编写子类LittleMonkey继承父类Monkey
class LittleMonkey extends Monkey implements Fishable, Birdable {

    // 因为父类没有无参构造,只有有参构造,所以子类必须实现父类指定的有参构造
    public LittleMonkey(String name) {
        super(name);
    }

    @Override
    public void swimming() {
        System.out.println(getName() + "通过学习,可以像鱼儿一样游泳...");
    }

    @Override
    public void flying() {
        System.out.println(getName() + "通过学习,可以像鸟儿一样飞翔...");
    }
}

小结:

  • 当子类继承了父类,就自动的拥有父类的功能
  • 如果子类需要扩展功能,可以通过实现接口的方式扩展
  • 可以理解为:实现接口 是 对Java单继承机制的一种补充

(五)接口的多态性

1.多态参数

        在前面的USB接口案例,UsbInterface既可以接收手机Phone对象,又可以接收相机Camera对象,就体现了接口的多态:

(1)接口类型的变量 可以指向 实现接口类的对象实例

(2)父类类型的变量 可以指向 实现父类的子类的对象实例

public class InterfacePloyParameter {
    public static void main(String[] args) {
        // 接口体现的多态:
        // 接口类型的变量 if01 可以指向 实现了IF接口类的对象实例
        IF if01 = new Monster();
        if01 = new Fish();

        // 继承体现的多态:
        // 父类类型的变量 aaa 可以指向 继承了AAA父类的子类的对象实例
        AAA aaa = new BBB();
        aaa = new CCC();
    }
}
interface IF{}

class Monster implements IF{}
class Fish implements IF{}

class AAA{}

class BBB extends AAA{}
class CCC extends AAA{}

2.多态数组

案例:

        在Usb接口数组中,存放Phone和Camera对象,Phone类还有一个特有的方法call(),Camera类还有一个特有的方法photo()。

        遍历Usb数组:如果是Phone对象,除了调用Usb 接口定义的方法外,还需要调用Phone特有方法call();如果是Camera对象,除了调用Usb接口定义的方法外,还需要调用Camera特有方法photo()

代码实现:

public class InterfacePolyArr {
    public static void main(String[] args) {
        //多态数组 -> 接口类型数组
        Usb[] usbs = new Usb[2];
        usbs[0] = new Phone_();
        usbs[1] = new Camera_();
       
        for (int i = 0; i < usbs.length; i++) {
            usbs[i].work();//动态绑定..
            // 和前面一样,我们仍然需要进行类型的 向下转型
            if (usbs[i] instanceof Phone_) {// 判断usbs[i]的运行类型是 Phone_
                ((Phone_) usbs[i]).call();
            } else if (usbs[i] instanceof Camera_) {
                ((Camera_) usbs[i]).photo();
            }
        }
    }
}

interface Usb {
    void work();
}

class Phone_ implements Usb {
    // Phone_特有的方法
    public void call() {
        System.out.println("手机可以打电话...");
    }

    @Override
    public void work() {
        System.out.println("手机工作中...");
    }
}

class Camera_ implements Usb {
    // Camera_特有的方法
    public void photo() {
        System.out.println("相机拍照更清晰...");
    }

    @Override
    public void work() {
        System.out.println("相机工作中...");
    }
}

3.接口存在多态传递现象

        如果类A实现了接口IN1,类A必须要实现接口IN1的抽象方法;如果接口IN1还继承了接口IN2,那么类A也必须要实现接口IN2的抽象方法。这就是接口的多态传递现象。

public class InterfacePolyPass {
    public static void main(String[] args) {
        //接口类型的变量可以指向,实现了该接口的类的对象实例
        IG ig = new Teacher();
        //如果IG 继承了 IH 接口,而Teacher 类实现了 IG接口
        //那么,实际上就相当于 Teacher 类也实现了 IH接口.
        //这就是所谓的 接口多态传递现象.
        IH ih = new Teacher();
    }
}

interface IH {
    void hi();
}

interface IG extends IH {
}

class Teacher implements IG {
    @Override
    public void hi() {
    }
}

(六)练习题

System.out.println(x);是否正确?

public class InterfaceExercise02 {
    public static void main(String[] args) {
        new C().pX(); // 0  1
    }
}

interface AB {
    int x = 0;
}  // 等价 public static final int x = 0;

class BB {
    int x = 1;
} //普通属性

class C extends BB implements AB {
    public void pX() {
        //System.out.println(x); //错误,原因不明确x
        //可以明确指定x
        //访问接口的 x 就使用 AB.x
        //访问父类的 x 就使用 super.x
        System.out.println(AB.x + " " + super.x);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CoreGen项目实战——代码提交信息生成

数据与相关代码见文末 1.概述 源代码与自然语言之间的语义鸿沟是生成高质量代码提交信息的一个重大挑战。代码提交信息对于开发者来说非常重要,因为它们简明扼要地描述了代码更改的高层次意图,帮助开发人员无需深入了解具体实现即可掌握软件的演变过程。手动编写高质量的提交…

Vite多环境配置与打包:

环境变量必须以VITE开头 1.VITE_BASE_API&#xff1a; 在开发环境中设置为 /dev-api&#xff0c;这是一个本地 mock 地址&#xff0c;通常用于模拟后端接口。 2.VITE_ENABLE_ERUDA&#xff1a; 设置为 "true"&#xff0c;表示启用调试工具&#xff0c;通常是为了…

Elasticsearch学习笔记(六)使用集群令牌将新加点加入集群

随着业务的增长&#xff0c;陆续会有新的节点需要加入集群。当我们在集群中的某个节点上使用命令生成令牌时会出现报错信息。 # 生成令牌 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node出现报错信息&#xff1a; Unable to create enrollment…

VMware WorkStation Pro 15.5(低版本安装) 教学用

VMware WorkStation Pro 15.5(低版本安装) 教学用 文章目录 VMware WorkStation Pro 15.5(低版本安装) 教学用前言安装使用 前言 VMware Workstation Pro 15.5 是一款功能强大的桌面虚拟化软件&#xff0c;适用于在单台物理电脑上运行多个操作系统。它被广泛应用于软件开发、测…

【文献阅读】Attention Bottlenecks for Multimodal Fusion

Abstract 在多模态视频分类中&#xff0c;将各模态的最终表示或预测进行后期融合&#xff08;“后期融合”&#xff09;仍然是主流范式。为此&#xff0c;本文提出了一种基于 Transformer 的新型架构&#xff0c;该架构使用“融合瓶颈”在多个层次进行模态融合。与传统的成对自…

科研必备语料库

1. Corpus of Contemporary American English 链接&#xff1a;https://www.english-corpora.org/coca/ 2. Purdue Online Writing Lab 链接&#xff1a;https://owl.purdue.edu/owl/ 3. Academic Phrases and Vocabulary 链接&#xff1a;https://www.ref-n-write.com/blog…

IntelliJ IDE 插件开发 | (十三)自定义项目脚手架(下)

系列文章 本系列文章已收录到专栏&#xff0c;交流群号&#xff1a;689220994&#xff0c;也可点击链接加入。 前言 在上一篇文章中介绍了如何在 IDEA 中自定义项目脚手架&#xff0c;本文将介绍如何在WebStorm、PyCharm、CLion等其它 IntelliJ 主流平台中如何自定义项目脚手…

【论文速看】DL最新进展20241006-视频深度估计、3D、自监督学习

目录 【视频深度估计】【3D】【自监督学习】 【视频深度估计】 [TPAMI 2024] NVDS: Towards Efficient and Versatile Neural Stabilizer for Video Depth Estimation 论文链接&#xff1a;https://arxiv.org/pdf/2307.08695 代码链接&#xff1a;https://github.com/RaymondW…

地理空间数据存储与处理:MySQL空间数据类型的优化与应用!

在 MySQL 数据库中&#xff0c;空间数据类型用于存储和处理地理空间数据。这些数据类型允许我们在开发时可在数据库中存储和操作地理位置、几何形状和地理空间关系等信息。 一、什么是空间数据类型 MySQL 中的空间数据类型主要包括以下几种&#xff1a; GEOMETRY&#xff1a…

【无人水面艇路径跟随控制3】(C++)USV代码阅读: ROS包的构建和管理:包的依赖关系、包含目录、库文件以及链接库

【无人水面艇路径跟随控制3】&#xff08;C&#xff09;USV代码阅读&#xff1a; ROS包的构建和管理&#xff1a;包的依赖关系、包含目录、库文件以及链接库 写在最前面ROS是什么CMakeLists.txt总结详细解释CMake最低版本和项目名称编译选项查找catkin包catkin包配置包含目录添…

(刷题记录5)盛最多水的容器

盛最多水的容器 题目信息&#xff1a;题目思路(环境来自力扣OJ的C)&#xff1a;暴力枚举&#xff1a;双指针&#xff1a;移动高度较高的指针移动高度较低的指针 复杂度&#xff1a;代码与注释&#xff1a;暴力枚举&#xff1a;双指针&#xff1a; 题目信息&#xff1a; 给定一…

windows 找不到文件 Microsoft Net Framework 3.5 windows Driver Foundation(WDF).exe

问题 正常更新windows 11的时候发现这个问题。 重启也无法完成下面的更新&#xff0c;重启之后还是显然要更新&#xff1a; 解决方法 中文网站没有找到解决方案。微软官网总是给不靠谱的解决方案。 从有关上看到一个印度语音的视频&#xff0c;用的方法可行。借鉴过来。 …

【机器学习】机器学习框架

机器学习框架是支持开发、训练、和部署机器学习模型的工具集和库&#xff0c;以下是一些主流的机器学习框架及其特点&#xff1a; 1. TensorFlow 特点: 由 Google 开发&#xff0c;支持从研究到生产的大规模部署&#xff0c;广泛应用于深度学习模型。优势: 强大的可扩展性&am…

golang gin入门

gin是个小而精的web开发框架 官方文档 安装 go get -u github.com/gin-gonic/gin最简单的起手代码 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON…

【自用】王道文件管理强化笔记

文章目录 操作系统引导:磁盘初始化文件打开过程角度1文件的打开过程角度2 内存映射的文件访问 操作系统引导: ①CPU从一个特定主存地址开始&#xff0c;取指令&#xff0c;执行ROM中的引导程序(先进行硬件自检&#xff0c;再开机) ②)将磁盘的第一块–主引导记录读入内存&…

【机器学习】深度学习、强化学习和深度强化学习?

深度学习、强化学习和深度强化学习是机器学习的三个重要子领域。它们有着各自独特的应用场景和研究目标&#xff0c;虽然都属于机器学习的范畴&#xff0c;但各自的实现方式和侧重点有所不同。 1. 深度学习&#xff08;Deep Learning&#xff09; 深度学习是一种基于神经网络的…

2024 年在线翻译谁称霸?论文翻译场景大揭秘!

现在这世界&#xff0c;语言就是把我们连在一起的绳子&#xff0c;挺关键的。不管搞研究、做生意还是传文化&#xff0c;翻译得又快又准。2024年&#xff0c;翻译这行竞争挺猛的&#xff0c;各种在线翻译工具都挺拼的。咱们今天就聊聊论文翻译&#xff0c;瞅瞅谁能在这场翻译比…

Meta 发布 Quest 3S 头显及 AR 眼镜原型:开启未来交互新视界

简介 在科技的浪潮中&#xff0c;Meta 始终站在创新的前沿&#xff0c;不断为我们带来令人惊叹的虚拟现实和增强现实体验。2024 年 10 月 6 日&#xff0c;让我们一同聚焦 Meta 最新发布的 Quest 3S 头显及 AR 眼镜原型&#xff08;Orion&#xff09;&#xff0c;探索这两款产品…

【Blender Python】5.Blender场景中的集合

概述 这里的“集合”是指Blender场景中的集合。你可以在“大纲视图”面板中看到 图标的&#xff0c;就是集合&#xff0c;可以看做是文件夹&#xff0c;用于分类和整理场景中的对象。 获取场景的集合 >>> C.scene bpy.data.scenes[Scene]>>> C.scene.coll…

nodejs 构建高性能服务器的关键技术

nodejs 构建高性能服务器的关键技术 演示地址 演示地址 源码地址 源码地址 获取更多 获取更多 在现代 Web 开发中&#xff0c;Node.js 已成为构建高性能、可扩展网络应用的首选平台之一。它的非阻塞 I/O 模型与事件驱动架构使其能够在处理大量并发请求时表现出色&#xff0…