java第四次作业

JAVA第四次作业

(一)学习总结

1.学习使用思维导图对Java面向对象编程的知识点(封装、继承和多态)进行总结。

2.阅读下面程序,分析是否能编译通过?如果不能,说明原因。应该如何修改?程序的运行结果是什么?为什么子类的构造方法在运行之前,必须调用父 类的构造方法?能不能反过来?

    class Grandparent {
        public Grandparent() {
            System.out.println("GrandParent Created.");
        }
        public Grandparent(String string) {
            System.out.println("GrandParent Created.String:" + string);
        }
    }
    class Parent extends Grandparent {
        public Parent() {        
            System.out.println("Parent Created");
            super("Hello.Grandparent.");
        }
    }
    class Child extends Parent {
        public Child() {
            System.out.println("Child Created");
        }
    }
    public class Test{
        public static void main(String args[]) {
            Child c = new Child();
        }
    } 

不能编译通过

  • 原因 : super("Hello.Grandparent.");,构造函数调用语句必须放在子类构造方法中的首句,该语句不符合。

  • 修改为:

     class Parent extends Grandparent {
             public Parent() {
             	 super("Hello.Grandparent.");
                 System.out.println("Parent Created");
             }
         }      
    
  • 运行结果为:
    GrandParent Created.String:Hello.Grandparent.
    Parent Created
    Child Created

  • 子类对象在实例化之前必须首先调用父类中的构造方法后再调用子类自己的构造方法,调用父类的构造方法是用父类的构造方法为父类中的属性初始化,就表示先有父类实例,然后才有子类实例。

  • 不能,子类继承了父类的各种属性,而构造方法则相当于把父类给实例化出来,如果子类实例化的时候不调用父类的构造方法,相当于子类压根就没有父亲,如果反过来,父类根本不知道子类有什么变量,这样子类也得不到初始化的父类变量,就会导致程序运行出错!

3 . 阅读下面程序,分析程序中存在哪些错误,说明原因,应如何改正?正确程序的运行结果是什么?

    class Animal{
      void shout(){
          System.out.println("动物叫!");
      }
    }
    class Dog extends Animal{
          public void shout(){  
              System.out.println("汪汪......!");  
         }
          public void sleep() {
           System.out.println("狗狗睡觉......");
          } 
    }
    public class Test{
        public static void main(String args[]) {
            Animal animal = new Dog(); 
            animal.shout();
            animal.sleep();
            Dog dog = animal;
            dog.sleep(); 
            Animal animal2 = new Animal();
            dog = (Dog)animal2;
            dog.shout();
        }
    }
  • 测试类中语句存在错误,该题用到了对象的多态性,向下转型时,语句错误,向上转型时,父类不可以直接调用子类的方法,应在父类中定义sleep方法,所以应修改为:

        class Animal{
               void shout(){
                   System.out.println("动物叫!");
               }
               void sleep(){
                 System.out.println();
             }
             }
             class Dog extends Animal{
                   public void shout(){  
                       System.out.println("汪汪......!");  
                  }
                   public void sleep() {
                    System.out.println("狗狗睡觉......");
                   } 
             }
             public class Test{
                 public static void main(String args[]) {
                     Animal animal = new Dog(); 
                     animal.shout();
                     animal.sleep();
                     Dog dog = animal;
                     dog.sleep(); 
                     Animal animal2 = new Animal();
                     dog = (Dog)animal2;
                     dog.shout();
                 }
             }
    
  • 正确程序运行结果:
    汪汪......!
    狗狗睡觉......
    狗狗睡觉......
    汪汪......!

4.运行下列程序

    class Person { 
       private String name ; 
       private int age ; 
       public Person(String name,int age){ 
             this.name = name ; 
             this.age = age ; 
       } 
    }
    public class Test{  
          public static void main(String args[]){ 
                 Person per = new Person("张三",20) ; 
                 System.out.println(per);
                 System.out.println(per.toString()) ; 
      } 
    }

(1)程序的运行结果如下,说明什么问题?

Person@166afb3
Person@166afb3

  • System.out.println(per);
    System.out.println(per.toString())
    这两个语句中加与不加toString()最终的输出结果是一样的,说明对象输出时一定会调用Object类中的toString()方法打印内容。

(2)那么,程序的运行结果到底是什么呢?利用eclipse打开println(per)方法的源码,查看该方法中又调用了哪些方法,能否解释本例的运行结果?

  • 张三,20
    该方法中又调用了公共的父类Objrct

(3)在Person类中增加如下方法

public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}

重新运行程序,程序的执行结果是什么?说明什么问题?
(可参考教材P229)

  • 运行结果:
    姓名:张三,年龄:20
    姓名:张三,年龄:20
  • Person类中覆写了Object类中的toString()方法,直接输出对象时调用的是被子类覆写过的toString()方法。

5.其他需要总结的内容

向上转型后,父类也只能调用父类已经有的方法。但是子类如果覆盖了父类的方法,那么即使向上转型,方法的行为也表现为覆盖后的行为。这也是多态的一种体现。向上转型更多的用来体现一种编程上的“约定”。所有继承某个类或者实现某个接口的类,一定包含某个方法,这样在调用的时候,使得你也不必关系具体的实现细节,只要知道“这个类型中的某个方法能帮我完成工作”就可以了。

向下转型是“引用的类型”的变化,不是对象实例类型的变化。new什么,就是什么。不会因为向上或者向下转型而改变自己的类型。

  • 多态:同一个对象(事物),在不同时刻体现出来的不同状态。
    举例:
    猫是猫,猫是动物。
    水(液体,固体,气态)。

  • 多态的前提:
    A:要有继承关系。
    B:要有方法重写。
    其实没有也是可以的,但是如果没有这个就没有意义。
    动物 d = new 猫();
    d.show();
    动物 d = new 狗();
    d.show();
    C:要有父类引用指向子类对象。

(二)实验总结

实验内容:

1.定义员工类,具有姓名、年龄、性别属性,并具有构造方法和显示数据方法。定义管理层类,继承员工类,有自己的属性职务和年薪。定义职员类,继承员工类,并有自己的属性所属部门和月薪。定义一个测试类,进行测试。画出类图。
工具:ProcessOn
参考资料:UML 类图

  • 程序设计思路:定义Worker父类,在定义Clerk,Straff子类继承Worker类,用super关键字调用Worker类中指定的构造方法,测试类中调用覆写过的方法。参考教材187页例题
    问题:子类不能调用父类中的构造方法
    原因:没有正确使用super关键字
    解决方案:经过参考教材得知,super语句必须放在子类构造方法的首行

    public Clerk(String name,int age,String sex,String bumen,int yuexin){
    	    	super(name,age,sex);
    	    	this.setBumen(bumen);
    	    	this.setYuexin(yuexin);
    

    }

  • 类图

2.按照下面要求完成类的设计
(1)设计一个平面图形抽象类(提供求该类对象周长和面积的方法)和一个立体图形抽象类(提供求该类对象表面积和体积的方法)
(2)设计球类、圆柱类,圆锥类、矩形类、三角形类、圆类,分别继承平面图形抽象类和立体图形抽象类。
(3)建立测试类,进行测试。画出类图。

  • 程序设计思路:定义抽象类父类,属性为double类
    问题:球的体积和圆锥的体积计算结果不对
    原因:公式中除号用的方法不对
    解决方案:公式中所需的4/3应分开写,例如求圆锥体积的公式4/3PIrrr应写为4PIrrr/3

  • 类图

3.. 参考类图,重构下面的实例,分析和理解多态的含义和用途
(1)某动物园有一饲养员小李,每天需要给他所负责饲养的一只狮子、五只猴子和十只鸽子喂食。 请用一个程序来模拟他喂食的过程。分析这种编程方式有什么不合理的地方。
(2)第一次重构,引入继承,利用抽象类和对象多态重构程序,Animal类采用抽象类, 合并Feeder类中的方法分析程序是否还可以进一步优化

(3)第二次重构,修改feedAnimals方法,让它接收一个Animal数组通过本题的重构,说一下多态有什么好处。在第二次重构之后,是否就能应对各种场景了呢?你认为还应该做哪些优化?

  • 多态的好处:提高了代码的维护性(继承保证)和代码的扩展性(由多态保证)
  • 不能应对各种场景

完成实验内容,代码上传到码云,按照题目要求画出类图,回答问题,并对完成实验内容过程中遇到的问题、解决方案以及程序的设计思路和思考等进行归纳总结。

  • 程序设计思路:定义Animal,Lion,Monkey,Pigeon,Feeder类,用数组,循环,求和函数写测试类,建立类之间的联系。
    问题:测试类遇到问题
    原因:未解决

(三)代码托管

码云commit历史截图

原文地址:https://www.cnblogs.com/HQY110/p/6722059.html