完成 3-3 的内容

master
高宏宇 2 years ago
parent 5f1ef27f00
commit 39bdaab6f1

@ -504,6 +504,8 @@ class Fruit extends Object{
}
```
其实Object是所有引用类型最终的“根”每个引用类型都是Object直接或者间接的子类。
### 4.1. toString方法
这样以来所有引用类型都具备Object所具备的所有能力最常用的就是toString()方法。
@ -549,6 +551,7 @@ classDiagram
+toString()
+printInfo()
}
Apple <|-- GiantApple
```
有三个类Fruit是父类Apple和Orange都从Fruit扩展而来且都覆盖了其toString()方法。
@ -590,19 +593,17 @@ public class Test {
这样理解可能会好一些:
1. 变量类型声明是**调用能力声明**
2. 对一个对象的能力声明并不一定是该对象的全部能力;
3. 子类型对象的能力一定不小于父类型对象的能力;
上面例子中真实的对象是Apple能力声明是Fruit。因为Apple的能力不小于Fruit因此我用Fruit类型声明的变量去调用Apple的对象不存在任何问题。但 是因为能力声明的限制只能调用Fruit这个类型所具备的能力例如Orange类型有一个printInfo()函数,就无法在 Fruit的引用变量上调用
1. 变量类型声明只是**调用能力声明**
2. 子类型对象的能力一定不小于父类型对象的能力;
上面例子中真实的对象是Apple能力声明是Fruit。因为Apple的能力不小于Fruit因此我用Fruit类型声明的变量去调用Apple的对象不存在任何问题Apple的能力大于FruitFruit的能力只是Apple能力的一个子集。但是因为能力声明的限制引用变量的类型只能调用Fruit这个类型所具备的能力例如Orange类型有一个`printInfo()`函数,就无法在 Fruit的引用变量上调用
上面的例子有些抽象,我们举一个生活中具体的例子:
但是为什么输入结果不是`This is fruit`?这时因为子类型覆盖了父类型的`toString()`方法;真正的行为表现形式还要看对象的确切类型是什么。例子中,对象是 Apple 或者是 OrangetoString()的行为也只能是Apple或者Orange对应这个函数的真是行为而不是他父类的行为父类的这个行为被覆盖了。关于这个问题在下面的动态函数绑定中还有解释。
用父类型的引用变量引用字类型的对象,并调用相应的函数体现不同的行为,这就是多态。多态应用中,子类型一般需要覆盖父类型的方法。
### 5.2. 复杂一点的例子
### 5.2. 参数中使用多态
我们先来看看一个例子:
@ -621,39 +622,355 @@ public class Test {
}
```
这里例子中
同样,函数的参数也可以使用父类型,这样的调用和上面变量类型使用父类型其实是一样的。
### 5.3. 动态函数绑定
子类型覆盖了父类型的函数,哪么当通过引用变量调用一个对象某个函数的时候,不是编译的时候决定的(静态),而而是在运行的时候,引用变量引用的真实对象所决定的(对象决定行为,不是引用变量类型),这样的方式叫做动态函数绑定。
```java
public class DynamicBindingDemo {
public static void main(String[] args) {
m(new GraduateStudent());
m(new Student());
m(new Person());
m(new Object());
}
public static void m(Object x) {
System.out.println(x.toString());
}
}
class GraduateStudent extends Student {
}
class Student extends Person {
public String toString() {
return "Student";
}
}
class Person extends Object {
public String toString() {
return "Person";
}
}
```
上述例子执行的结果是:
```
Student
Student
Person
java.lang.Object@7e774085
```
虽然`m(Object x)`的引用变量类型是 Object在其中调用 toString() 方法toString()方法是在Object中定义的因此每个类型都具备该方法当然可以覆盖但是其行为是右具体的对象确定的。
书上的解释:
> When the method m(Object x) is executed, the argument xs toString method is invoked. x may be an instance of GraduateStudent, Student, Person, or Object. Classes GraduateStudent, Student, Person, and Object have their own implementation of the toString method. Which implementation is used will be determined dynamically by the Java Virtual Machine at runtime. This capability is known as dynamic binding.
>
> Dynamic binding works as follows: Suppose an object o is an instance of classes C1, C2, ..., Cn-1, and Cn, where C1 is a subclass of C2, C2 is a subclass of C3, ..., and Cn-1 is a subclass of Cn. That is, Cn is the most general class, and C1 is the most specific class. In Java, Cn is the Object class. If o invokes a method p, the JVM searches the implementation for the method p in C1, C2, ..., Cn-1 and Cn, in this order, until it is found. Once an implementation is found, the search stops and the first-found implementation is invoked.
上面文字使用下面的例子来解释Apple这个例子中我们再次扩展Apple为一个GiantApple类
```java
sclass GiantApple extends Apple {
}
public class Test {
public static void main(String[] args) {
Fruit fruit = new GiantApple();
System.out.println(fruit.toString()); // 打印This is an apple.
}
}
```
上述代码的输出任然是`This is an apple.`。真实对象是`GiantApple`,而`GiantApple`没有toString()方法因此Java会顺着继承的关系一层一层向上去找父类的toString()的实现当找到的第一个个toString()的实现就调用。`GiantApple`没有toString()实现,因此在其父类`Apple`中寻找,找到了,就执行。
## 6. 引用类型的类型转换
我们把上述的法则增加一条:
1. 变量类型声明只是**调用能力声明**
2. 子类型对象的能力一定不小于父类型对象的能力;
3. 真正的行为表现要看其具体对象的类型,而不是看引用变量的类型。
这样我们多态的规则就完备了。凡是以后关于多态的问题都可以由以上三条规则解释。
### 6.1. 子类型转换成父类型
更准确的说应该是父类型的引用变量引用子类型的对象,就像前面的:
```java
Fruit fruit = new Apple();
```
这样总是成功的这里没有显式explicit 的进行类型转换而叫做隐式implicit 类型转换。其隐含的语义是Apple也是水果。只不过我们通过fruit引用变量只能调用类型Fruit所能调用的变量和函数能力声明
更进一步来说,下面的语法也是完全正确的:
```java
Object object = new Apple();
```
因为 Object 类型是所有引用类型的共同祖先因此其语义是Apple也是对象。当然通过object引用变量所能调用的变量或者函数相对Apple这个类型来说可能就更少了。
下面的也是合法的:
```java
Apple apple = new GiantApple();
Object objedt = apple;
```
对比一下,我们多态的三条规则,是不是可以理解?
### 6.2. 父类型转换成子类型
#### 6.2.1. 非强制转换
这里有两种情况:首先是子类型的引用变量引用父类型的对象:
## 7. equals 方法
```java
Orange orange = new Fruit(); // 非法
```
或者是这样:
```java
Fruit fruit = new Fruit();
Orange orange = fruit; // 非法
```
## 8. ArrayList类
这样的操作是非法的,因为:
1. 真实对象是Fruit
2. 引用变量类型是 Orange
3. Orange是Fruit的子类型其能力大于准确的说是不小于Fruit
4. 用较大的能力声明去定义一个较小能力的对象而对其进行调用可能造成能力不匹配的问题。例如Orange 有一个`printInfo()`的方法而Fruit没有当用 `orange.pringInfo()`进行调用的时候,因为真实对象不具备这个能力,所以导致出错。
因此:父类型赋值给子类型是非法的!其隐含的语义是 Fruit 是 Orange这显然是不正确的。
## 9. protected 访问修饰
#### 6.2.2. 强制转换
真实对象是子类型,而引用变量是父类型,这种情况是合法的。但是否可以转换回去?例如:
```java
Object object = new GiantApple(); // 合法
Orange orange = object; // 非法
```
这为什么变成非法的了答案是因为动态绑定的特性编译器不知道引用变量的object的真实类型因为object变量可以引用所有的引用类型对象。那如果非要这么做应该怎么办答案是强制类型转换或者叫做显式explicit )类型转换:
```java
Object object = new Orange(); // 合法
Orange orange = (Orange)object; // 合法,强制类型转换
orange.printInfo(); // 正确真实对象是Orange,有这个能力
```
但是你能保证object引用的真是一个Orange对象吗
```java
Object object = new Apple(); // 合法
Orange orange = (Orange)object; // 合法,强制类型转换
orange.printInfo(); // 语法正确,运行抛出异常
```
因为真实对象是Apple不具备printInfo()的能力。那么这是就需要用到 instanceof 操作符了。
### 6.3. instanceof 操作
## 10. final 修饰
instanceof 操作符是用来判断一个引用变量所引用对象的类型其语义是该对象是属于XXX类吗
**注意只能操作引用类型对原始类型Primitive操作是语法错误。**
```Java
Object object = new Apple();
if (object instanceof GiantApple) System.out.println("GiantApple"); // 不输出
if (object instanceof Apple) System.out.println("Apple"); // 输出
if (object instanceof Object) System.out.println("Object"); // 输出
```
非常有用的一个操作符号,有了这个,先判断成功后再进行强制类型转换就一定不会出错了。我们来看看一个更复杂的例子:
```java
public class Test {
public static void main(String[] args) {
Fruit[] fruits = {new Apple(), new Orange(), new Apple(), new Orange(), new GiantApple()}; // 水果的数组
whatFruit(fruits); // 调用统计函数
}
// 统计水果的种类
static void whatFruit(Fruit[] fruits) {
int countApple = 0;
int countOrange = 0;
for (Fruit fruit : fruits) { // 增强for循环
if (fruit instanceof Apple) { // 判断是Apple
countApple++;
}
if (fruit instanceof Orange) { // 判断是 Orange
countOrange++;
Orange orange = (Orange) fruit; // 类型强制转换,一定成功
orange.printInfo(); // 调用 Orange 专属的能力
}
}
System.out.printf("We have %d apples.\n", countApple);
System.out.printf("We have %d oranges.\n", countOrange);
}
}
```
有了上面的例子,是不是清楚多了。
注意强制类型转换只能用作同一个类属的继承关系中其语义是属于某个类例如Apple属于FruitOrange属于FruitApple属于Object。但是不同类属将不能进行强制类型转换例如Orange和Apple这两个类没有属于的这种语义属于不同的分支人和猴子属于不同的分支说人属于猴子或者猴子属于人都是不正确的。如下图
```mermaid
classDiagram
Object <|-- Fruit
Fruit <|-- Apple
Fruit <|-- Orange
Fruit : +toString()
class Apple{
+toString()
}
class Orange{
+toString()
+printInfo()
}
Apple <|-- GiantApple
```
## 7. ArrayList类
ArrayList 是比Array更好的一个“数组”。相比传统的数组ArrayList是动态的且提供更多的操作。
```java
import java.util.ArrayList;
public class TestArrayList {
public static void main(String[] args) {
// Create a list to store cities
ArrayList<String> cityList = new ArrayList();
// Add some cities in the list
cityList.add("London");
// cityList now contains [London]
cityList.add("Denver");
// cityList now contains [London, Denver]
cityList.add("Paris");
// cityList now contains [London, Denver, Paris]
cityList.add("Miami");
// cityList now contains [London, Denver, Paris, Miami]
cityList.add("Seoul");
// contains [London, Denver, Paris, Miami, Seoul]
cityList.add("Tokyo");
// contains [London, Denver, Paris, Miami, Seoul, Tokyo]
System.out.println("List size? " + cityList.size());
System.out.println("Is Miami in the list? " + cityList.contains("Miami"));
System.out.println("The location of Denver in the list? " + cityList.indexOf("Denver"));
System.out.println("Is the list empty? " + cityList.isEmpty()); // Print false
// Insert a new city at index 2
cityList.add(2, "Xian");
// contains [London, Denver, Xian, Paris, Miami, Seoul, Tokyo]
// Remove a city from the list
cityList.remove("Miami");
// contains [London, Denver, Xian, Paris, Seoul, Tokyo]
// Remove a city at index 1
cityList.remove(1);
// contains [London, Xian, Paris, Seoul, Tokyo]
// Display the contents in the list
System.out.println(cityList.toString());
// Display the contents in the list in reverse order
for (int i = cityList.size() - 1; i >= 0; i--)
System.out.print(cityList.get(i) + " ");
System.out.println();
// Create a list to store two circles
java.util.ArrayList<CircleFromSimpleGeometricObject> list = new java.util.ArrayList<>();
// Add two circles
list.add(new CircleFromSimpleGeometricObject(2));
list.add(new CircleFromSimpleGeometricObject(3));
// Display the area of the first circle in the list
System.out.println("The area of the circle? " + list.get(0).getArea());
}
}
```
掌握书上这个例子应该是足够了。注意ArrayList的声明方式这是泛型申明。关于泛型我们只需要知道如何使用就可以了不用关心太多。
```java
ArrayList<String> cityList = new ArrayList();
```
尖括号中的就是泛型表达的语义是ArrayList中转载的数据是什么类型。当然如果是`ArrayList<Object>`那么可以装任何的引用类型。
**注意:泛型中尖括号中的类型必须是引用类型,不能是原始类型。**
需要了解ArrayList和Array间的相互转换
```java
public static void main(String[] args) {
// Creating an ArrayList from an array of objects:
String[] array = { "red", "green", "blue" };
ArrayList<String> list = new ArrayList<>(Arrays.asList(array));
// Creating an array of objects from an ArrayList:
String[] array1 = new String[list.size()];
list.toArray(array1);
}
```
## 8. protected 访问修饰
现在我们可以完整访问修饰符了。有了继承后,有了一个新的修饰符叫做 protected比 public更严格比 缺省 更宽松;其含义是允许其子类型拥有完全的访问,而不关心是否在同一个包当中。记住下面这张表格就可以了。
![image-20230314095131138](img/image-20230314095131138.png)
下图是一个例子:
![image-20230314095222682](img/image-20230314095222682.png)
### 8.1. 不能降低父类成员的访问级别
> A subclass may override a protected method in its superclass and change its visibility to public. However, a subclass cannot weaken the accessibility of a method defined in the superclass. For example, if a method is defined as public in the superclass, it must be defined as public in the subclass.
>
> 子类可以覆盖其超类中的受保护方法并将其可见性更改为公共。然而子类不能削弱在超类中定义的方法的可访问性。例如如果一个方法在超类中定义为public那么它在子类中必须定义为public。
如何理解我们规则第2条子类型的能力永远不小于父类型的能力。类型的能力是其成员可见性觉得的可见性降低了其能力降低。因此不能弱化可访问性可见性
访问修饰的从严格到宽松的排序private<default<protected<public
### 8.2. final 修饰
> The final class cannot be extended;
>
> The final variable is a constant;
>
> The final method cannot be overridden by its subclasses.
注意:
> The modifiers are used on classes and class members (data and methods), except that the final modifier can also be used on local variables in a method. A final local variable is a constant inside a method.
>
> 修饰符用于类和类成员数据和方法但final修饰符也可以用于方法中的局部变量。final用于一个局部变量这个变量就是方法内部的常量。

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

@ -0,0 +1,113 @@
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="401px" height="241px" viewBox="-0.5 -0.5 401 241" content="&lt;mxfile&gt;&lt;diagram id=&quot;gjUDRqYtxhnxVrKjGRsl&quot; name=&quot;第 1 页&quot;&gt;zVhLb9swDP41ug525Id0tB2nuwwY0MO2oxsriTEnChynSfbrR0r0K3G8Ft26AsEmUaIofvxE0mU82Z4fqmy/+aJzVbKZk58Zn7PZzHV8Cf+h5GIlYehYwboqctrUCR6LX6rRJOmxyNVhsLHWuqyL/VC41LudWtYDWVZV+jTcttLl0Oo+W6sbweMyK2+l34q83lipmIWd/LMq1pvGshuQw9us2UyeHDZZrk89EU8ZTyqtazvanhNVIngNLlZvcWe1vVildvVLFGZW4Tkrj+QbS30WO0wscBDNWRSwNGTSYxIkCxYnTEa4JGP8wUAIJiVLAxaH+MMlB4WpYPECx6AepUwSOIf60sBY6eMuV3gTh/H4tClq9bjPlrh6AuKAbFNvS5i5MLz1jJx9VlWtzj0Refqg9FbV1QW20OqME+pEOzeg+akLoitJtukFsNHLiDfr9ugOWhgQuuNIh7dIX+OhcmAZTXd6p14IwEEfqyUdwek1ZNVa1YMQ4+GTIFWqzOrieUjxt3jMR7mFdJmz1GOxQHqNcwvGEVJKJixKzADoJQ2TBBPxh2NSO38PJsm3Mgn8ri7fEaxPfjP90V+bnwlJO7vQ7EUM9G8ZyP82A0n1qy7gIm1QeGObgsKvwbZ3Iq0rvNtrvCgE/gi1JYsgJYq71BYJLQmJuTGCVfsgIG3ODcdN4v34ZOfOO5K9Kfn/OG8Gt6z1/1feDEbzZuQhZe7VZCQX0CfFSovEgd+Csq0I3sagVVGWiS51ZXT5SizVcgnyQ13pn6q38iR8z5/ME2/gXPienHNHImCfbkRtDT5UQBcg54g3/BvbZmhhgPdwGvkmSgm+YXjVWPjs8xZmD2i5RivEqic8sweSiDSRdDEdjJhoq6QpjsIZK5e9A8nWn1q6LjeZdg0au3j0Pu3mvnU4Oe05aM6Jo0nOctQVgHFQQtzipwpG69pQ50YyhaohOMai9wgQBDF2+RYWE0FIu22G7VJ27xxEPsDNgpsE7WP0ZTwGVGsUPJ0xmRqjiQHhVZ4KfL6xxXDexcv20Ndsub1YgLpx23m3MbXtVtNcERM8vJ4w2QIxDHomfHQBYXnl5dGo+RKIHPMlYCnhNoFLxkJpXAaedLRp4bVBmSaSRIukHmGqo8CFpCXCqbw4BWbLBOuXuHPyvWdloXMnO14fOwA0MdE6TNywjc5VdocUWw9T+DBVU4ns53USZWWx3sG0VCs8AdN1AV+9EYm3RZ6jkdGKMawpd/L9SFW4WwK88OprTY6UgGCkBLje62sATLuPbtsQdn+64Olv&lt;/diagram&gt;&lt;/mxfile&gt;">
<defs/>
<g>
<rect x="0" y="0" width="190" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 15px; margin-left: 1px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
小学生:四则混合运算
</div>
</div>
</div>
</foreignObject>
<text x="95" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
小学生:四则混合运算
</text>
</switch>
</g>
<path d="M 95 70 L 95 36.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
<path d="M 95 31.12 L 98.5 38.12 L 95 36.37 L 91.5 38.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
<rect x="0" y="70" width="190" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 85px; margin-left: 1px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
初中生:基本方程
</div>
</div>
</div>
</foreignObject>
<text x="95" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
初中生:基本方程
</text>
</switch>
</g>
<path d="M 95 140 L 95 106.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
<path d="M 95 101.12 L 98.5 108.12 L 95 106.37 L 91.5 108.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
<rect x="0" y="140" width="190" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 155px; margin-left: 1px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
高中生,三角函数方程
</div>
</div>
</div>
</foreignObject>
<text x="95" y="159" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
高中生,三角函数方程
</text>
</switch>
</g>
<path d="M 95 210 L 95 176.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
<path d="M 95 171.12 L 98.5 178.12 L 95 176.37 L 91.5 178.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
<rect x="0" y="210" width="190" height="30" fill="#f8cecc" stroke="#b85450" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 225px; margin-left: 1px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
大学生,微积分
</div>
</div>
</div>
</foreignObject>
<text x="95" y="229" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
大学生,微积分
</text>
</switch>
</g>
<rect x="240" y="30" width="160" height="140" fill="none" stroke="none" pointer-events="all"/>
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 158px; height: 1px; padding-top: 100px; margin-left: 242px;">
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;">
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
上述关系可以看成是类的扩展关系:最基本的是小学生,一直扩展,最后成为大学生。
<br/>
<br/>
可以看到,在扩展的过程中,其能力一直在增强。
<br/>
<br/>
记住子类的能力永远不会小于父类型。
<br/>
<br/>
这样我们可以认为一个大学生除了具备微积分的能力,还具备小学生、初中生和高中生的能力。
</div>
</div>
</div>
</foreignObject>
<text x="242" y="104" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">
上述关系可以看成是类的扩展关系:最基本的是小学生,一直扩展,最后成为大学生。可以看到,在扩展的过程中,其能力一直在增强。记住子类的能力永远不会小于父类型。这样我们可以认为一个大学生除了具备微积分的能力,还具备小学生、初中生和高中生的能力。...
</text>
</switch>
</g>
</g>
<switch>
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
<a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
<text text-anchor="middle" font-size="10px" x="50%" y="100%">
Text is not SVG - cannot display
</text>
</a>
</switch>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

Loading…
Cancel
Save