8.接口与抽象类 深入多态

news2024/11/27 0:47:01

8.1 不该初始化的class

这个结构有什么不对?
这个class结构不算太差。如此设计已经能够维持最少的重复程序代码,且有需要特地实现的方法也已经被覆盖过。从多态的角度来看,我们也做到了适应性,所以任何Animal的子型,包括编写程序时无法想象的种类,也能够传递给取用Animal类型的方法来执行。我们已经加上了所有Animal的共同协议到父类上,现在可以开始创建新的Lion等对象。

我们可以写出这样的指令:

        Wolf aWolf = new Wolf();

也可以这样:

        Animal aHippo = new Hippo();

但是这样会很奇怪:

        Animal anim = new Animal(); 

实例变量的值会是……?
有些类不应该被初始化!

创建出Wolf对象或Hippo对象或Tiger对象是很合理的,但是Animal对象呢?它应该长什么样子?什么颜色、大小、几条腿?
尝试创建出Animal类型的对象就好像出人意料之外,在传送组合的过程中发生了一点问题。
那要如何处理这个问题呢?我们一定要有Animal这个类来继承和产生多态。但是要限制只有它的子类才能够被初始化。我们要的是Lion、Hippo对象,而不是Animal对象。

幸好,有个方法能够防止类被初始化。换句话说,就是让这个类不能被“new”出来。通过标记类为抽象类的,编译器就知道不管在哪里,这个类就是不能创建任何类型的实例。
你还是可以用这种抽象的类型作为引用类型。这也就是当初为何要有抽象类型的目的。

当你设计好继承结构时,你必须要决定哪些类是抽象的,而哪些是具体的。具体的类是实际可以被初始化为对象的。
设计抽象的类很简单——在类的声明前面加上抽象类关键词abstract就好:

abstract public class Canine extends Animal {
    public void roam() { }
}

8.2 抽象类

编译器不会让你初始化抽象类

抽象类代表没有人能够创建出该类的实例。你还是可以使用抽象类来声明为引用类型给多态使用,却不用担心哪个创建该类型的对象,编译器会确保这件事。

抽象类除了被继承过之外,是没有用途、没有值、没有目的(除了抽象的class可以有static的成员之外,见第10章) 

抽象与具体

不是抽象的类就被称为具体类。在Animal的继承树下,如果我们创建出Animal、Canine与Feline的抽象,则Hippo、Wolf等就是具体的类。

查阅Java API你就会发现其中有很多的抽象类,特别是GUI的函数库中更多。GUI的组件类是按钮、滚动条等与GUI有关类的父类。你只会对组件下的具体子类作初始化动作。

抽象或具体?
你怎么知道某个类应该是抽象的?饮料或许是抽象的。那大雕参茸或威士忌是否也应该是抽象的?在继承层次中从哪个点开始才算是具体的?
你会把“提神饮料”设计成具体,还是说它也是个抽象?看起来“保力达 B”才会是具体的。你认为呢?
观察上面的Animal继承层次,这些抽象或具体的决定是否合适呢?你会修改这个层次吗?

8.3 抽象方法

抽象的方法

除了类之外,你也可以将方法标记为abstract的。抽象的类代表此类必须要被extend过,抽象的方法代表此方法一定要被覆盖过。你或许认为抽象类中的某些行为在没有特定的运行时不会有任何的意义。也就是说,没有任何通用的实现是可行的。想象一下通用的eat()方法会有什么结果?

抽象的方法没有实体!因为你已经知道编写出抽象方法的程序代码没有意义,所以不会含有方法。

如果你声明出一个抽象的方法,就必须将类也标记为抽象的。你不能在非抽象类中拥有抽象方法。
就算只有一个抽象的方法,此类也必须标记为抽象的。

你必须实现所有抽象的方法

实现抽象的方法就如同覆盖过方法一样

抽象的方法没有内容,它只是为了标记出多态而存在。这表示在继承树结构下的第一个具体类必须要实现出所有的抽象方法。

然而你还是可以通过抽象机制将实现的负担转给下层。例如说将Animal与Canine都标记为abstract,则Canine就无需实现出Animal的抽象方法。但具体的类,例如说Dog,就得实现出Animal和Canine的抽象方法。

记得抽象类可以带有抽象和非抽象的方法,因此Canine也可以实现Animal的抽象方法,让Dog不必实现这个部分。如果Canine没有对Animal的抽象类表示出任何意见,就表示Dog得自己实现出Animal的抽象方法。

当我们谈到“你必须实现所有抽象的方法”时,表示说你必须写出内容。你必须以相同的方法鉴名(名称与参数)和相容的返回类型创建出非抽象的方法。Java很注重你的具体子类有没有实现这些方法。

8.4 多态的引用

多态的使用

假设我们不知道有ArrayList这种类而想要自行编写维护list的类以保存Dog对象。在第一轮我们只会写出add()方法。我们使用大小为5的简单Dog数组(Dog[])来保存新加入的Dog对象。当Dog对象超过5个时,你还是可以调用add()方法,但是什么事情也不会发生。如果没有越界,add()会把Dog装到可用的数组位置中,然后递增可用索引(nextlndex)

糟了,也要写出Cat用的

我们有几个选项:
(1)另外创建一个单独的MyCatList类来处理Cat对象,这不好。
(2)创建一个单独的DogAndCatList类,用addCat(Cat c)与addDog(Dog d)来同时处理两个不同的数组实例,这也不好。
(3)编写一个不同的AnimalList类让它处理Animal所有的子类。这应该是最好的办法,所以我们就这么处理,以更通用的Animal来取代个别的子类。程序变更得关键部分有特别标出来(逻辑还是一样,只是把Dog换成Animal)

public class MyAnimalList {
    private Animal[] animals = new Animal[5];
    private int nextIndex = 0;
    
    public void add(Animal a) {
        if (nextIndex < animals.length) {
            animals[nextIndex] = a;
            System.out.println("Animal added at " + nextIndex);
            nextIndex++;
            
        }
    }
}
public class AnimalTestDrive {
    public static void main(String[] args) {
        MyAnimalList list = new MyAnimalList();
        Dog a = new Dog();
        Cat c = new Cat();
        list.add(a);
        list.add(c);
    }
}

8.5 对象之母:Object

非Animal呢?何不写个万用类?

你知道这要怎么做。我们可以修改数组的类型,并且调整add()方法的参数,以处理Animal之上的类。那便是更通用、更抽象的一种类。但是真的有这种类吗?我们设计的Animal并没有父类不是吗?

事实上是有的。

还记得ArrayList的方法吗?它们是通过对象这个类型来操纵所有类型的对象。

在Java中的所有类都是从Object这个继承出来的。

Object这个类是所有类的源头;它是所有对象的父类。

如果Java中没有共同的父类,那将无法让Java的开发人员创建出可以处理自定义类型的类,也就是说无法写出像ArrayList这样可以处理各种类的类。

就算你不知道,但实际上所有的类都是从对象给继承出来的。你可以把自己写的类想象成是这样声明的:

public class Dog extends Object ( )

但是Dog本来是从Canine给extends出来的啊!没关系,编译器会知道改成让Canine去继承对象。
事实上是Animal去继承对象。

没有直接继承过其他类的类会是隐含的继承对象。

所以就算Dog或Canine没有直接extend对象,还是会通过Animal来继承对象。

终极对象有什么? 

如果你是Java,那你会想要让每个对象都带有什么行为?嗯……来个可以判断某对象是否与其他对象相等的方法如何?再加上一个可以说明它是什么类的方法怎样?或许还会需要一个产生对象哈希代码的方法?你可以运用哈希表上的对象(我们会在第17章和附录B中讨论哈希表)。

你知道怎样吗?对象的确有上面所说的方法。那还不是全部的方法,但目前我们只关心这几个。

8.6 取出数组元素

使用Object类型的多态引用是会付出代价的

在你开始以Object类型使用所有超适用性参数和返回类型之前,你应该要考虑到使用Object类型作为引用的一些问题。注意此处的讨论不涉及制作出Object类型的实例,这是在说以Object类型作为引用的其他类型。
当你把对象装进ArrayList<Dog>时,它会被当作Dog来输入与输出:

但若你把它声明成ArrayList<Object>时会怎样?如果你打算创建出一个可以保存任何一种对象的
ArrayList时,你会如此的声明: 

如果是这样,当你尝试要把Dog对象取出并赋值给Dog的引用时会发生什么事? 

任何从ArrayList<Object>取出的东西都会被当作Object类型的引用而不管它原来是什么

从ArrayList<Object>取出的Object都会被当作是Object这个类的实例。编译器无法将此对象识别为Object以外的事物。

当Dog不再是Dog时 

问题在于把所有东西都以多态来当作是Object会让对象看起来失去了真正的本质(但不是永久性的)。Dog似乎失去了犬性。让我们来看一下当我们传入一个Dog给会返回同一个Dog对象的类型引用的方法时会有什么反应。

8.7 编译器对引用类型的检查

Object不会吠
我们已经知道当一个对象被声明为Ob-ject类型的对象所引用时,它无法再赋值给原来类型的变量。我们也知道这会发生在返回类型被声明为Object类型的时候,例如前面所提过的ArrayList<Object>。但这意味着什么呢?使用Object引用变量来引用Dog对象会是个问题吗?让我们试着对被编译器认为是Object的Dog调用Dog才有的方法看看:

编译器是根据引用类型来判断有哪些method可以调用,而不是根据Object确实的类型。

就算你知道对象有这个功能,编译器还是会把它当作一般的Object来看待。编译器只管引用的类型,而不是对象的类型。

8.8 探索内部对象

探索内部Object

对象会带有从父类继承下来的所有东西。这代表每个对象,不论实际类型,也会是个Object的实例。所以Java中的每个对象除了真正的类型外,也可以当作是Object来处理。当你执行new Snowboard)命令时,除了在堆上会有一个Snow-board对象外,此对象也包含了一个Object在里面。

8.9 多态引用

“多态”意味着“很多形式”

你可以把Snowboard当作Snowboard或者Object

如果引用是个遥控器,则当你在继承树往下走时,会发现遥控器的按钮越来越多。Object的遥控器只有几个按钮而已,但Snowboard的遥控器就会包含有来自Object和自己定义的按钮。越接近具体的类会有越多的按钮。

当然这也不是绝对的,子类也有可能不会加入任何新的方法,而只是覆盖过一些方法罢了。重点在于如果对象的类型是Snowboard,而引用它的却是Object,则它不能调用Snowboard的方法。

当你把对象装进ArrayList<Object>时,不管它原来是什么,你只能把它当作是Object。从ArrayList<Object>取出引用时,引用的类型只会是Object。这代表你只会取得Object的遥控器。

8.10 对象引用类型转换

转换回原来的类型

它还是个Dog对象,但如果你想要调用Dog特有的方法,就必须要将类型声明为Dog。如果你真的确定它是个Dog,那么你就可以从Object中拷贝出一个Dog引用,并且赋值给Dog引用变量。

    Object o = al.get(index);
    Dog d = (Dog) o;
    d.roam();

如果不能确定它是Dog,你可以使用instanceof这个运算符来检查。若是类型转换错了,你会在执行期遇到ClassCastException异常并且终止。 

    if (o instanceof Dog) {
        Dog d = (Dog) o;
    }

现在你知道Java是多么注重引用变量的类型。

你只能在引用变量的类确实有该方法才能调用它。把类的公有方法当作是合约的内容,合约是你对其他程序的承诺协议。

在编写类时,大多数情况下你一定会显露出一些方法给类以外的程序使用。要让方法显露就代表你会让方法能够存取得到,通常这会通过标记成公有来完成。

想象这样的情境:你在编写一个小型会计总账系统给“猪标服装社”使用。你发现有个称为
Account的类已经写好并且符合你的需求(上一次帮“宏昌水电行”开发程序时写出来的),因此就把它拿过来用。

它有一个debit()和credit()方法可以用来执行会计的借贷项目,还有getBlance()方法可以计算账户。

所以你可以声明一个变量a引用到Account的实例,然后通过圆点运算符调用a.debit()或a.credit()等。因为类的合约是这么保证的,所以你在这个类的实例上面一定能找到这些方法。

万一想要修改合约呢?

好吧,假如你是个Dog(但是千万别去闻另外一个Dog的屁股,这样很不礼貌),你会发现不只有一份合约,你还继承了所有父类传递下来的方法。

类Canine中的所有元素是你合约中的一部分。类Animal中的所有元素是你合约中的一部分。类Object中的所有元素是你合约中的一部分。

根据IS-A测试,你就会是Canine、Animal和Object。

如果有人要编写类似的程序,你大可把定义好的class交给他使用。

但是,如果他还要加上亲热或耍宝等宠物特有的功能要怎么办呢?

现在假设你是设计Dog类的程序设计师。没问题吧?你可以直接把beFriendly()和play()这两个方法加进Dog这个类中。这样做不会让其他用到Dog的程序产生问题,因为你没有更改到其他现有的方法。你觉得这样的做法(把Pet的方法直接加到Dog上)有没有缺点?

如果你是Dog类的程序设计师,且必须修改Dog类以让它能够执行Pet的动作,那你会怎么办?我们知道直接加入Pet的方法是可行的,并且这也不会对其他程序有影响。

但若Cat也要有Pet的功能怎么办?先不管Java的功能,想象一下你要怎样让Animal可以选择性地带有Pet的行为又不会强迫让狮子老虎都表现成宠物?

有哪些方法可以在PetShop程序中重用现有的类?

方法一:

采用最简单的做法,把宠物方法加进Animal类中

优点:

所有的动物马上就可以继承宠物的行为。不需要改变所有子类的程序代码,而新增加的动物也会取得同样的行为。

缺点:

你什么时候看过宠物店贩卖河马?又是什么时候看到饲主跟河马亲热,带河马去公园散步?
并且我们也知道狗跟猫表现亲热的方式不太一样啊。

方法二: 

采用方法一,但是把宠物的方法设定成抽象的,强迫每个动物子类覆盖它们

优点:

这样就可以让非宠物类的动物在覆盖这些方法时,作出合理的动作,或者是什么也不作。

缺点:

所有具体的动物都得实现宠物的行为,这样很浪费时间。
并且这种合约不太理想,不论有没有实质的行为,非宠物也得声明出有宠物行为的外观,对狮子老虎的尊严是个打击。
最重要的是这会让Animal的定义变得有些局限性,反而让其他类型的程序更难以重复利用。

方法三:

把方法加到需要的地方

优点:

不必担心如何跟河马亲热。只有宠物才会有宠物的行为。

缺点:

首先,这样就会失去了物该有的合约保证。你无法确定宠物可以执行的是doFriendly()还是beFriendly()。
其次,多态将无法起作用,因为Animal不会有共同的宠物行为,你得针对个别宠物设计程序。

所以我们真正需要的方法是:

(1)一种可以让宠物行为只应用在宠物身上的方法。
(2)一种确保所有宠物的类都有相同的方法定义的方法。
(3)一种是可以运用到多态的方法。 

8.11 多重继承的麻烦

这种“多重继承”可能会很差。其实Java不支持这种方式,因为多重继承会有称为“致命方块”的问题“致命方块”(因为这个形状看起来就像扑克牌的方块)

允许致命方块的程序语言会产生某种很糟糕的复杂性问题,因为你必须要有某种规则来处理可能出现的模糊性。额外的规则意味着你必须同时学习这些规则与观察适用这些规则的特殊状况。因此Java基于简单化的原则而不允许这种致命方块的出现。好吧,问题还是没有解决…… 

8.12 使用接口

接口是我们的救星!

Java有个解决方案,使用接口。此处所讨论的不是GUI的接口,也不是“沟通管道”或“存取途径”的接口,我们说的是Java的interface关键词。

此接口可以用来解决多重继承的问题却又不会产生致命方块这种问题。

接口解决致命方块的办法很简单:把全部的方法设为抽象的!如此一来,子类就得要实现此方法,因此Java虚拟机在执行期间就不会搞不清楚要用哪一个继承版本。

接口的定义: 

public interface Pet {...}

接口的实现: 

public class Dog extends Canine implements Pet {...}

设计与实现Pet接口

public interface Pet {
    public abstract void beFriendly();
    public abstract void play();
}

public class Dog extends Canine implements Pet{
    public void beFriendly() {...}
    public void play() {...}
    
    public void roam() {...}
    public void eat() {...}
}

不同继承树的类也可以实现相同的接口

当你把一个类当作多态类型运用时,相同的类型必定来自同一个继承树,而且必须是该多态类型的子类。定义为Canine类型的参数可以接受Wolf与Dog,但无法忍受Cat或Hippo。
但当你用接口来作为多态类型时,对象就可以来自任何地方了。唯一的条件就是该对象必须是来自有实现此接口的类。允许不同继承树的类实现共同的接口对Java API来说是非常重要的。如果你想要将对象的状态保存在文件中,只要去实现Serializable这个接口就行。打算让对象的方法以单独的线程来执行吗?没问题,实现Runnable。有概念了吧。后面的章节会有关于Serializable与Runnable的讨论,现在只要先掌握住这个概念就行。

更棒的是类可以实现多个接口!

通过继承结构,Dog对象IS-A Canine、IS-A Animal、IS-A Object。但Dog IS-A Pet是通过接口实现的机制达成的,并同时也能够实现其他的接口:

public class Dog extends Animal implements Pet, Saveable, paintable{...}

瑰是红的,自我感觉是良好的,extend只能有一个,implement可以有好多个。类来自单亲家庭(superclass),但可以扮演多重角色(implement)。

要如何判断应该是设计类、子类、抽象类或接口呢?

如果新的类无法对其他的类通过IS-A测试时,就设计不继承其他类的类。

只有在需要某类的特殊化版本时,以覆盖或增加新的方法来继承现有的类。

当你需要定义一群子类的模板,又不想让程序员初始化此模板时,设计出抽象的类给它们用

如果想要定义出类可以扮演的角色,使用接口。

调用父类的方法

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

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

相关文章

什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对这几篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc;什么是SpringMVC&#xff1f;简单好理解&#xff01;什么是应用分层&#xff1f;SpringMVC与应用分层的关系&#xff1f; 什么是三层架构&…

【Unity细节】为什么UI移动了锚点,中心点和位置,运行的时候还是不在设置的位置当中

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

从行车记录仪恢复已删除/丢失视频的方法

“我的车里有行车记录仪。几天前&#xff0c;当我下班回家时&#xff0c;一辆卡车不知从哪里冒出来撞向了我。我们的两辆车都损坏了&#xff0c;但幸运的是&#xff0c;没有人受伤。我曾与卡车司机就修理我的汽车进行过会面&#xff0c;但他说我有错。我需要查看我的行车记录仪…

微服务注册中心之安装+实例搭建zookeeper

1.下载安装包并上传到Linux服务器 Apache ZooKeeper 可以使用wget或者curl命令 wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.7.1/apache-zookeeper-3.7.1-bin.tar.gz连接失败也可以本地下载之后上传到服务器 scp /本地/文件的/路径 用户名远程服务器IP或主…

(免费领源码)java#SSM#mysql基于响应式的网上书店系统27119-计算机毕业设计项目选题推荐

摘 要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理系统的实施在技术上已逐步成熟。管理系统是一个不断发展的新型学科&#xff0c;本文主要通过对响应式的网上书店系统的功能性需求分析&#xff0c;对系统的安全性和可扩展性进行了非功能性需求分析。在详细的…

【Proteus仿真】【Arduino单片机】OLED液晶显示

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用IIC OLED液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;OLED液晶显示各种图形、字符、图像。 二、软件设计 /* 作者&#xff1a;嗨小…

C++标准模板(STL)- 类型支持 (类型属性,is_bounded_array,is_unbounded_array)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实例…

时间序列预测模型实战案例(八)(Informer)BestPaper论文模型Informer代码实战讲解

论文地址->Informer论文地址PDF点击即可阅读 代码地址-> 论文官方代码地址点击即可跳转下载GIthub链接 本文介绍 本篇博客带大家看的是Informer模型进行时间序列预测的实战案例&#xff0c;它是在2019年被提出并在ICLR 2020上被评为Best Paper&#xff0c;可以说Inform…

如何再kali中下载iwebsec靶场

这个靶场有三种搭建方法&#xff1a; 第一种是在线靶场&#xff1a;http://www.iwebsec.com:81/ 第二种是虚拟机版本的&#xff0c;直接下载到本地搭建 官网地址下载&#xff1a;http://www.iwebsec.com/ 而第三种就是利用docker搭建这个靶场&#xff0c;我这里是用kali进行…

【CIO人物展】厦门市妇幼保健院CIO李振叶:医院数字化转型是迈向智慧医院新时代的关键...

李振叶 本文由厦门市妇幼保健院CIO李振叶投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 厦门市妇幼保健院&#xff08;厦门大学附属妇女儿童医院&#xff09;创建于1959年&#xff0c;是集保健、医疗、教学、科研…

代码随想录二刷Day 59

647. 回文子串 这个题的dp定义想不到&#xff0c;递推公式也想不到但是看题解都很容易理解&#xff0c;遍历顺序不太好理解。 class Solution { public:int countSubstrings(string s) {vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false)…

AI系统ChatGPT程序源码+AI绘画系统源码+支持GPT4.0+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

2.JMeter压测接口

概述 今日目标&#xff1a; JMeter使用 配置线程组配置 HTTP 接口配置断言 配置响应断言配置断言响应时间 配置结果监听压测报告 接口准备聚合报告察看结果树其它 线程组配置详解 线程数Ramp-Up bug结束 JMeter使用 双击 ApacheJMeter.jar 启动&#xff0c;然后修改名称&a…

Linux笔记-对/dev/vda1和/dev/vda2的理解

首先是这张图&#xff1a; 对于&#xff1a; /dev/vda1和/dev/vda2 可以知道&#xff0c;这个机器是在虚拟机上的&#xff0c;从设备描述中可以看到&#xff0c;与IO有关。 问下ChatGPT 问&#xff1a;linux上 /dev/vda1 和 /dev/vda2是干嘛的 答&#xff1a; /dev/vda1和…

GPT技术的崛起:改变生活与挑战未来

GPT的广泛使用引发了许多关于其影响的讨论&#xff0c;包括可能对就业和互联网公司的存活造成挑战。在这篇博客中&#xff0c;我们将探讨这些问题&#xff0c;并分享我们自己在日常生活中如何使用GPT的经验。 1 GPT技术的广泛应用 GPT&#xff0c;或者通用预训练模型&#x…

软件开发项目文档系列之十一如何撰写系统部署方案

目录 1 引言1.1 编写目的1.2 定义1.3 预期读者1.4 参考资料 2 系统部署要求2.1 硬件要求2.2 软件要求 3 系统结构描述3.1 逻辑结构3.2 物理拓扑 4 系统部署方案4.1 服务器资源4.2 软件资源4.3 应用服务器部署4.3.1 部署描述4.3.2 系统软件4.3.3 系统软件配置 4.4 MYSQL数据库服…

Python 海龟绘图基础教学教案(一)

Python 海龟绘图——第 1 题 题目&#xff1a;绘制下面的图形 解析&#xff1a; 考察 turtle 基本命令&#xff0c;绘制直线&#xff0c;使用 forward&#xff0c;可缩写为 fd。 答案&#xff1a; import turtle as t t.fd(100) # 或者使用 t.forward(100) t.done() Python 海…

【linux进程控制(二)】进程等待--父进程是如何等待子进程死亡的?

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; ) 这里写目录标题 1. 前言2. …

一 Java初探

初识Java Java是一门高级语言,如 Python、C、C++、Ruby 和 JavaScript一样。 那么要运行用高级语言编写的程序,必须将其转换为低级语言 (即“机器语言”)有两种将高级语言转换为低级语言的程序:解释器和编译器。解释器(interpreter): 读取并执行用高级语言编写的程序,如…

STM32存储左右互搏 SPI总线读写FLASH W25QXX

STM32存储左右互搏 SPI总线读写FLASH W25QXX FLASH是常用的一种非易失存储单元&#xff0c;W25QXX系列Flash有不同容量的型号&#xff0c;如W25Q64的容量为64Mbit&#xff0c;也就是8MByte。这里介绍STM32CUBEIDE开发平台HAL库操作W25Q各型号FLASH的例程。 W25QXX介绍 W25QX…