Java学习第五章重点

5.7对象的上转型对象

这一节是本章(子类与继承)的重点内容。

举个例子:

我们常说“老虎是动物”、“狗是动物”等。动物类是老虎类的父亲,这样说也没有问题,但要注意,当我们说“老虎是动物”的时候,老虎将失去老虎独有的属性和功能。
从人的思维方式上看,“老虎是动物”属于上溯思维

1
2
3
A a;
B b = new B();
a = b;//称a为b的上转型对象。

(1) 上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)。
(2) 上转型对象可以访问子类 继承或隐藏 的成员变量,也可以调用子类继承的方法或子类 重写 的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类 重写了父类的某和实例方法 后,当对象的上转型对象调用这个实例方法时一定是调用了子类 重写的实例方法

注意事项:

  1. 不要将父类创建的对象和子类对象的上转型混淆。
  2. 可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所有的属性和功能。
  3. 不可以将父类创建的对象的引用赋值给子类声明的对象(不能说“人是美国人”)。
  4. 如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写的静态方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package 第五章;

class A {
int m;
int getM(){
return m;
}
int seeM()
{
return m;
}
}
class B extends A {
int m;
int getM()
{
return m+100;
}
}
public class Example_5_7 {

public static void main(String[] args) {
// TODO Auto-generated method stub
B b=new B();
A a=null;
b.m=20;
System.out.println(b.getM());//B类中重写了方法
a=b;
a.m=-100;
System.out.println(a.getM());//上转型对象调用的是重写的方法

System.out.println(b.seeM());//子类继承的方法调用的是隐藏变量
}

}

输出:

1
2
3
120
120
-100

5.8继承与多态

多态性是指父类的某个方法被其子类重写的时候,可以各自产生自己的功能行为。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package 第五章;

public class Example_5_8 {

public static void main(String[] args) {
// TODO Auto-generated method stub
动物 animal=null ;
animal = new 狗();
animal.cry();
animal = new 猫();
animal.cry();
}

}
class 动物{
void cry(){

}
}

classextends 动物
{
void cry()
{
System.out.println("汪汪汪……");
}
}
classextends 动物
{
void cry()
{
System.out.println("喵喵喵……");
}
}

5.9 abstract类与abstract方法(抽象类与抽象方法)

用abstract 修饰的类或方法,就叫做抽象类或抽象方法。
不能用final 和 abstract 同时修饰一个方法或类 也不能用static 修饰 abstract方法,即 abstract方法必须是实例方法。
类似摘要,方法体是由子类重写。

重点:

  1. abstract 类中可以有 abstract方法 不能有方法体
  2. abstract 类不能用new 运算符创建对象(可以直接声明,但不能用new)
  3. abstract 类的子类,必须有子类,所以不能有final修饰,子类必须重写抽象类方法。
  4. abstract 类的对象作上转型对象,抽象类的对象做子类对象,调用与子类相同
  5. 理解abstract:让开发者注重行为的标准,而不是细节,作用类似于摘要,宏观的战略布局,细节方面交给子类来完善。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package 第五章;
abstract class GirlFriend
{
abstract void speak();//不需要方法体
abstract void cooking();///不需要方法体
}
class ChinaGirlFriend extends GirlFriend//多态用法
{

@Override
void speak() {
System.out.println("你好!\n");
}

@Override
void cooking() {
System.out.println("我会做烤牛排\n");
}

}
class AmericanGirlFriend extends GirlFriend//多态用法
{

@Override
void speak() {
System.out.println("Hello, nice to meet you!\n");
}

@Override
void cooking() {
System.out.println("roast beef");
}

}
class Boy
{
GirlFriend friend;
void setGirlfriend(GirlFriend f)
{
friend = f;
}
void showGirlFriend()
{
friend.speak();
friend.cooking();
}
}
public class Example_5_9 {

public static void main(String[] args) {
GirlFriend girl =null;
ChinaGirlFriend f = new ChinaGirlFriend();
girl = f;//上转型调用子类方法
Boy boy = new Boy();
boy.setGirlfriend(girl);
boy.showGirlFriend();
AmericanGirlFriend f1 = new AmericanGirlFriend();
girl = f1;//上转型调用子类方法
boy.setGirlfriend(girl);
boy.showGirlFriend();
}
}

输出:

1
2
3
4
5
6
7
你好!

我会做烤牛排

Hello, nice to meet you!

roast beef

5.10 难点:面向抽象编程

概念:所谓的面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。

例子:求柱体积

面对用户需求的变化,常规程序中可能会大幅度更改,会很麻烦。可以用抽象类概括用户的相似需求。

1
2
3
4
5
//抽象类
public abstract class Geometry
{
public abstract double getArea();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package 柱体体积;

public class Application {

public static void main(String[] args) {
Geometry bottom;//抽象对象
Pillar pillar;//体积对象
bottom = new Circle(10);//调用子类求底
pillar = new Pillar(bottom,20);//调用体积类,求体积方法
System.out.println("圆柱的体积是:"+pillar.getV());
bottom = new Rectangle(2,5);//调用子类求底
pillar = new Pillar(bottom,20);//调用体积类,求体积方法
System.out.println("长方体的体积是:"+pillar.getV());
bottom = new Sanjiaoxing(4,4);//调用子类求底
pillar = new Pillar(bottom,20);//调用体积类,求体积方法
System.out.println("三棱锥的体积是:"+pillar.getV());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package 柱体体积;
//体积计算
public class Pillar {
Geometry bottom;
double h;
Pillar(Geometry bottom,double h)//调用自身进行赋值
{
this.bottom=bottom;
this.h=h;
}
public double getV()//体积方法
{
if(bottom==null)
{
System.out.println("没有底");
return -1;
}
else
{
return bottom.getArea()*h;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 柱体体积;
//三角形底面积
public class Sanjiaoxing extends Geometry{

double d,h;
Sanjiaoxing(double d,double h)
{
this.d=d;
this.h=h;
}
public double getArea() {
return d*h*0.5;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
package 柱体体积;
//圆底面积
public class Circle extends Geometry{
double r;
Circle(double r)
{
this.r=r;
}
public double getArea() {
return (3.14*r*r);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package 柱体体积;
//矩形底面积
public class Rectangle extends Geometry {
double a,b;
Rectangle(double a,double b)//调用自身进行赋值
{
this.a=a;
this.b=b;
}
public double getArea() {
return a*b;
}
}

5.11 开——闭原则

所谓“开——闭原则”就是让设计的系统应当对扩展开放,对修改关闭。实际上,这句话的本质是:当系统中增加新的模块的时候,不需要修改现有的模块。

设计的核心部分一定是经过精心设计之后确定下来的基本结构,这部分应该是对修改关闭的,即不能因为用户的需求变化而在发生任何变化,因为这部分不是用来应对需求变化的

如果系统的设计遵守了“开——闭原则”,那么这个系统一定是易维护的,因为在系统中怎加模块的时候,不必去修改系统中的核心模块。

坚持原创技术分享,您的支持也将成为我的动力!
-------------本文结束感谢您的阅读-------------
undefined