【Java语言基础】面向对象之封装、继承、抽象类、接口、多态综合知识习题及总结day11

这几天逐渐被idea所折服,越来越喜欢这个优雅又强大的代码编辑器,有很多人说idea对很多初学者不友好,但是在我看来,只要你足够自律,并且英语不会太差,语法上关键的几个单词没什么大问题,idea对初学者是有很大帮助的。因为idea强大的语法检查功能对初学者十分友好,idea提供各种错误提示,以及各个需要注意的地方,这让初学者可以轻松找到出错的代码块。好了,下面来看题目吧!

1.根据以下这段话的描述,用面向对象的思想实现

狗生活在陆地上(是一种陆生动物),既是哺乳类的也是肉食性的。
狗通常的时候和人打招呼会通过“摇摇尾巴”,在被抚摸情绪很好的时候,
会“旺旺叫”,而在受到惊吓情绪烦躁时,会发出“呜呜”声;

猫也生活在陆地上(是一种陆生动物),既是哺乳类的也是肉食性的。
猫通常的时候和人打招呼会发出“喵~”的声音,在被抚摸情绪很好时,
会发出“咕噜咕噜”声,而在受到惊吓时,会发出“嘶嘶”声;

青蛙是一种两栖动物(既是水生动物也是陆生动物),既不是哺乳类的也不是肉食性的,
属于卵生。青蛙通常的时候和人打招呼会通过“呱呱叫”,当青蛙情绪好的时候,
会在岸边“呱呱呱”的唱歌,而在受到惊吓时,会“扑通一声跳入水中”

//下面只实现了狗的模块,猫和青蛙模块同理,不再赘述
//因为水生和陆生不能抽象处出来共性,因此将其定义为接口

package com.company;
abstract class Animal
{
    static final int HAPPY = 1;
    static final int UNHAPPY = 0;
    protected boolean carnivorous;  //肉食
    protected boolean mammal;  //哺乳
    public abstract void sayHello();
    public abstract void sayHello(int mood);

    public boolean isCarnivorous()
    {
        return carnivorous;
    }

    public boolean isMammal()
    {
        return mammal;
    }

}
//水生动物
interface Water
{
    boolean hasGillFlag();  //是否有腮
}
//陆生动物
interface Land
{
    int getLegNumber(); //有多少条腿
}

class Dog extends Animal implements Land
{
    private int dogLegNumber = 4;

    //访问父类的属性
    //父类使用权限protected
    Dog()
    {
        this.carnivorous = true;
        this.mammal = true;
    }
    public void sayHello()
    {
        System.out.println("摇摇尾巴");
    }
    public void sayHello(int mood)
    {
        switch (mood)
        {
            case HAPPY:
                System.out.println("汪汪叫");
                break;
            case UNHAPPY:
                System.out.println("呜呜叫");
                break;
            default:
                System.out.println("摇摇尾巴");
        }
    }
    public int getLegNumber()
    {
        return dogLegNumber;
    }
}

public class TaskDay09_4 {
    public static void main(String[] args)
    {
        Dog dog = new Dog();
        if(dog.mammal)
            System.out.println("狗是哺乳动物");
        else
            System.out.println("狗不是哺乳动物");

        if(dog.carnivorous)
            System.out.println("狗是肉食动物");
        else
            System.out.println("狗不是肉食性动物");

        System.out.print("狗通常的打招呼方式是:" );
        dog.sayHello();
        System.out.print("狗开心的时候的打招呼方式是:" );
        dog.sayHello(Animal.HAPPY);
        System.out.print("狗不开心的时候的打招呼方式是:" );
        dog.sayHello(Animal.UNHAPPY);
        System.out.println("狗是肉食动物,狗有" + dog.getLegNumber() + "条腿");
    }
}

总结:这道题因为水生和陆生不能抽象处出来共性,因此需要将其定义为接口

2.已知电脑有三个USB接口,分别去实例化一个鼠标,一个键盘,一个U盘来连接到电脑上。输出每一个USB接口连接的设备信息

package com.company;
interface Usb
{
    String getDeviceInfo();
}

class Mouse implements Usb
{
    public String getDeviceInfo()
    {
        return "鼠标";
    }
}

class KeyBoard implements Usb
{
    public String getDeviceInfo()
    {
        return "键盘";
    }
}

class Upan implements Usb
{
    public String getDeviceInfo()
    {
        return "U盘";
    }
}

class Computer
{
    private Usb usb1;
    private Usb usb2;
    private Usb usb3;
    public Computer(){}
    public Computer(Usb usb1, Usb usb2, Usb usb3)
    {
        this.usb1 = usb1;
        this.usb2 = usb2;
        this.usb3 = usb3;
    }
    public void showInfo()
    {
        System.out.println(usb1.getDeviceInfo());
        System.out.println(usb2.getDeviceInfo());
        System.out.println(usb3.getDeviceInfo());
    }
}

public class TaskDay09_1 {
    public static void main(String[] args)
    {
        Usb usb1 = new Mouse();
        Usb usb2 = new KeyBoard();
        Usb usb3 = new Upan();

        Computer com = new Computer(usb1, usb2, usb3);
        com.showInfo();
    }
}


总结:在做这道题的时候面向对象的思想不明确,导致题意不懂。
只需要将USB定义为接口,接口的作用是用来展示键盘、鼠标、U盘各个设备的信息。键盘、鼠标、U盘只需要分别定义为一个类实现接口即可。将电脑定义为一个类,其中包含了三个USB对象,并通过方法试实现展示功能。
注意:接口是抽象的,不能用来实例化对象,只能通过实现接口的各个类和实例化对象。因此在main函数中利用多态来实现函数功能。

3.设计一个交通工具抽象类,提供抽象方法–驾驶

汽车作为交通工具的一种,实现了驾驶的方法(在马路上驾驶)
火车作为交通工具的一种,实现了驾驶的方法(在铁路上驾驶)
飞机作为交通工具的一种,实现了驾驶的方法(在天上驾驶)
需求:做一个测试类,在测试类的main函数中,分别实例化一个汽车的对象,火车的对象和飞机的对象,并分别描述驾驶行为

package com.company;

abstract class Transportation
{
    abstract void Drive();
}

class Car extends Transportation
{
    public void Drive()
    {
        System.out.println("马路上行驶");
    }
}

class Train extends Transportation
{
    public void Drive()
    {
        System.out.println("铁路上行驶");
    }
}

class Plane extends Transportation
{
    public void Drive()
    {
        System.out.println("天上行驶");
    }
}

public class TaskDay09_2
{
    public static void main(String[] args)
    {
        Car car = new Car();
        Train train = new Train();
        Plane plane = new Plane();

        func(car);
        func(train);
        func(plane);
    }

    //多态:父类的引用指向了子类
    public static void func(Transportation tool)
    {
        tool.Drive();
    }
}

总结:同样的,这题也是通过多态实现,但是这题是抽象类,但是第2题是接口。
多态的过程细节:多态与继承、方法重写密切相关,我们在方法中接收父类类型作为参数,在方法实现中调用父类类型的各种方法。当把子类作为参数传递给这个方法时,java虚拟机会根据实际创建的对象类型,调用子类中相应的方法(存在方法重写时)。
因此可以继续总结多态实现的三个条件,一定要记下来!
1.需要有继承关系(普通子父类的继承和抽象类的继承)或者实现(接口)的存在。
2.需要有方法的重写。
3.需要有父类的引用指向子类对象。

4.设计一个家政服务规范(接口): 洗衣服, 扫地, 买菜, 做饭

设计一个保姆类, 保姆需要遵循这些规范
需求:在测试类中,实例化一个保姆的对象,然后让保姆买菜,做饭,扫地

package com.company;

interface Service
{
    void wishClothes();
    void sweepFloor();
    void cookRice();
}

class Nurse implements Service
{
    private String name;
    Nurse(){}
    Nurse(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }
    public void wishClothes()
    {
        System.out.println("wishClothes");
    }
    public void sweepFloor()
    {
        System.out.println("sweepFloor");
    }
    public void cookRice()
    {
        System.out.println("cookRice");
    }
}


public class TaskDay09_3
{
    public static void main(String[] args)
    {
        Nurse nurse = new Nurse("Tom");
        System.out.println(nurse.getName());
        show(nurse);
    }
    public static void show(Service ser)
    {
        ser.wishClothes();
        ser.sweepFloor();
        ser.cookRice();
    }
}

这一题同样是用到了多态,和上面两道题不一样的是,这一题里面的子类包含了自己特有的属性,因此先先定义了一个子类对象nurse,利用子类对象nurse对其属性先赋初始值。之后利用多态,创建ser(接口)对象,再将ser对象指向子类对象nurse,实例化的同样只是子类,而不是接口。
经过这三道题目的踪总结,对于多态应当有了更深入的理解。

5.设计一个动物类,属性: 姓名,性别

设计一个猫类,设计一个狗类, 猫和狗都继承自动物类
需求:在测试类中设计一个方法,这个方法需要一个参数,参数的类型可以是猫类,也可以是狗类 -->多态(动物类 )

package com.company;

abstract class Animals
{
    private String name;
    private String sex;

    Animals(){}

    Animals(String name, String sex)
    {
        this.name = name;
        this.sex = sex;
    }

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

    public void setSex(String sex)
    {
        this.sex = sex;
    }

    public String getName()
    {
        return name;
    }
    public String getSex()
    {
        return sex;
    }
}

class Cat extends Animals
{
    Cat(){}
    Cat(String name, String sex)
    {
        super(name, sex);
    }
}

class Dog1 extends Animals
{
    Dog1(){}
    Dog1(String name, String sex)
    {
        super(name, sex);
    }
}


class TaskDay09_4
{
    public static void main(String[] args)
    {
        Cat cat = new Cat("Tom","M");
        Dog1 dog1= new Dog1("Amy", "W");
        testAnimals(cat);
        testAnimals(dog1);
    }

    public static void testAnimals(Animals ani)
    {
        if (ani instanceof Cat)
        {
            //下面这段可以进行封装,但是懒。。。
            String name = ani.getName();
            String sex = ani.getSex();
            System.out.println(name);
            System.out.println(sex);
        }
        if (ani instanceof Dog1)
        {
            String name = ani.getName();
            String sex = ani.getSex();
            System.out.println(name);
            System.out.println(sex);
        }
    }
}

总结:认真做到这一道题目的时候已经对面向对象、抽象类、多态有比较深入的理解了!
1.抽象类也是一个类,也应当包含构造方法。
2.子类在继承抽象类时,构造方法应当重写,并继承父类的构造器。
3.为了更加细致地体现面向对象的思想,在main方法中定义的对象应当有明确的指向,例如Cat cat = new Cat(“Tom”,“M”); 此处定义的对象cat应当指向Cat类,而不是指向的Animals类,同时利用构造器对该对象赋初始值更加方便快捷
4.细节上来说,每次重写构造器时都应当写上该类的默认构造器,若不写上,则利用该类作为父类定义子类时,子类找不到父类的默认构造方法出现意想不到的错误。坚持一个良好习惯就成功了一半!

6.设计一个数据传输接口:Type-C标准

设计一个防水的接口:防水
设计一个手机类,实现这个数据传输接口,采用Type-C;同时实现了防水的接口

package com.company;

interface TypeC
{

}
interface waterProof
{

}
class Phone implements TypeC,waterProof
{

}
public class TaskDay09_5
{
    public static void main(String[] args)
    {
        Phone phone = new Phone();
    }
}

总结:实现多个接口

7.模拟 Arrays.sort 方法,实现如下方法,实现对一个Person数组的排序,给第二个参数传递对象时使用匿名内部类。

  MyArrays.sort(Person[] array, MyComparator comparator);
  Person是一个类,MyComparator是一个比较器,包含了compare抽象函数,需要使用匿名内部类重写
package com.company;

interface MyComparator
{
    int compare(Person ren1, Person ren2);

}

class Person
{
    private String name;
    private int age;
    public Person(){}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    //重写toString方法
    public String toString()
    {
        return name+"," +age;
    }
}

public class TaskDay09_6 {
    public static void main(String[] args)
    {
        Person[] arr = {new Person("lisi", 20), new Person("zhosi", 35),
        new Person("wangzi", 18), new Person("gangzi", 40), };
        sort(arr, new MyComparator(){
           public int compare(Person ren1, Person ren2)
           {
               return ren1.getAge() - ren2.getAge();
           }
        });

        for (Person person:arr)
        {
            System.out.println(person.toString());
        }
    }
	
	//选择排序,排序器用来比较大小的,只有这么一个功能
    public static void sort(Person[] array, MyComparator comparator)
    {
        for (int i=0; i<array.length-1; i++)
        {
            for(int j=i+1; j<array.length; j++)
            {
                if(comparator.compare(array[j], array[i])>0)
                {
                    Person temp = array[j];
                    array[j] = array[i];
                    array[i] = temp;
                }
            }
        }
    }
}

按照题目要求做即可,这里对Person排序指的是对Person里的age排序。
比较震撼的是lambda表达式,idea直接可以将匿名内部类换成lambda表达式,期待后面的学习

你可能感兴趣的:(Java基础)