14初级 - 面向对象:接口与抽象类-练习.md

219 阅读5分钟

14

1

  • world.java
package com.github.hcsp.polymorphism;

import java.util.Arrays;
import java.util.List;

public class World {
    // 现在有若干种对象,请尝试使用接口和抽象类将它们建造成类型体系
    // 以最大限度的复用、简化代码
    public static List<Object> objects =
            Arrays.asList(new 麻雀(), new 喜鹊(), new 蝴蝶(), new 飞机(), new 救护车(), new 猫(), new 狗());

    // 在建造成类型体系后,请尝试化简这个啰嗦的方法,体会多态带来的好处
    public static void 会飞的东西飞() {
        for (Object obj : objects) {
            if (obj instanceof 会飞的东西) {
                ((会飞的东西) obj).飞();
            }
        }
    }

    // 在建造成类型体系后,请尝试化简这个啰嗦的方法,体会多态带来的好处
    public static void 会叫的东西叫() {
        for (Object obj : objects) {
            if (obj instanceof 会叫的东西) {
                ((会叫的东西) obj).叫();
            }
        }
    }

    // 在建造成类型体系后,请尝试化简这个啰嗦的方法,体会多态带来的好处
    public static void 动物都能新陈代谢() {
        for (Object obj : objects) {
            if (obj instanceof 动物) {
                ((动物) obj).新陈代谢();
            }
        }
    }

    static class 麻雀 implements 会飞的东西, 会叫的东西, 动物 {


        @Override
        public void 叫() {
            System.out.println("叽叽喳喳");
        }
    }

    static class 喜鹊 implements 会飞的东西, 会叫的东西, 动物 {


        @Override
        public void 叫() {
            System.out.println("叽叽喳喳");
        }
    }

    static class 蝴蝶 implements 会飞的东西, 动物 {


        @Override
        public void 飞() {
            System.out.println("蝴蝶飞");
        }
    }

    static class 飞机 implements 会飞的东西 {
        @Override
        public void 飞() {
            System.out.println("飞机飞");
        }
    }

    static class 救护车 implements 会叫的东西 {
        @Override
        public void 叫() {
            System.out.println("哇呜哇呜");
        }
    }

    static class 猫 implements 会叫的东西, 动物 {


        @Override
        public void 叫() {
            System.out.println("喵喵喵");
        }
    }

    static class 狗 implements 会叫的东西, 动物 {


        @Override
        public void 叫() {
            System.out.println("汪汪汪");
        }
    }

    interface 动物 {
        default void 新陈代谢() {
            System.out.println("新陈代谢");
        }

    }

    interface 会飞的东西 {
        default void 飞() {
            System.out.println("鸟儿飞");
        }
    }

    interface 会叫的东西 {
        void 叫();
    }
}

2

  • User.java
package com.github.hcsp.polymorphism;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.TreeSet;

public class User implements Comparable<User> {
    /**
     * 用户ID,数据库主键,全局唯一
     */
    private final Integer id;

    /**
     * 用户名
     */
    private final String name;

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        User person = (User) o;

        return Objects.equals(id, person.id);
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }

    /**
     * 老板说让我按照用户名排序
     */
    @Override
    public int compareTo(User o) {
        if (name.compareTo(o.name) == 0) {
            return id.compareTo(o.id);
        } else {
            return name.compareTo(o.name);
        }
    }

    public static void main(String[] args) {
        List<User> users =
                Arrays.asList(
                        new User(100, "b"),
                        new User(10, "z"),
                        new User(1, "a"),
                        new User(2000, "a"));
        TreeSet<User> treeSet = new TreeSet<>(users);
        // 为什么这里的输出是3?试着修复其中的bug
        System.out.println(treeSet.size());
    }
}
  • 3
  • point.java
package com.github.hcsp.polymorphism;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Point implements Comparable<Point> {

    private final int x;
    private final int y;

    // 代表笛卡尔坐标系中的一个点
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Point point = (Point) o;

        if (x != point.x) {
            return false;
        }
        return y == point.y;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }

    @Override
    public String toString() {
        return String.format("(%d,%d)", x, y);
    }

    // 按照先x再y,从小到大的顺序排序
    // 例如排序后的结果应该是 (-1, 1) (1, -1) (2, -1) (2, 0) (2, 1)
    public static List<Point> sort(List<Point> points) {
        Collections.sort(points);
        return points;
    }

    public static void main(String[] args) throws IOException {
        List<Point> points =
                Arrays.asList(
                        new Point(2, 0),
                        new Point(-1, 1),
                        new Point(1, -1),
                        new Point(2, 1),
                        new Point(2, -1));
        System.out.println(Point.sort(points));
    }

    @Override
    public int compareTo(Point that) {
        if (this.x < that.x) {
            return -1;
        } else if (this.x > that.x) {
            return 1;
        }

        if (this.y < that.y) {
            return -1;
        } else if (this.y > that.y) {
            return 1;
        }
        return 0;
    }
}
  • 4

3

  • point.java
package com.github.hcsp.polymorphism;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Point implements Comparable<Point> {

    private final int x;
    private final int y;

    // 代表笛卡尔坐标系中的一个点
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Point point = (Point) o;

        if (x != point.x) {
            return false;
        }
        return y == point.y;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }

    @Override
    public String toString() {
        return String.format("(%d,%d)", x, y);
    }

    // 按照先x再y,从小到大的顺序排序
    // 例如排序后的结果应该是 (-1, 1) (1, -1) (2, -1) (2, 0) (2, 1)
    public static List<Point> sort(List<Point> points) {
        Collections.sort(points);
        return points;
    }

    public static void main(String[] args) throws IOException {
        List<Point> points =
                Arrays.asList(
                        new Point(2, 0),
                        new Point(-1, 1),
                        new Point(1, -1),
                        new Point(2, 1),
                        new Point(2, -1));
        System.out.println(Point.sort(points));
    }

    @Override
    public int compareTo(Point that) {
        if (this.x < that.x) {
            return -1;
        } else if (this.x > that.x) {
            return 1;
        }

        if (this.y < that.y) {
            return -1;
        } else if (this.y > that.y) {
            return 1;
        }
        return 0;
    }
}

4

  • user.java
package com.github.hcsp.polymorphism;

import com.sun.org.apache.xpath.internal.operations.Bool;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class User {
    /**
     * 用户ID,数据库主键,全局唯一
     */
    private final Integer id;

    /**
     * 用户名
     */
    private final String name;

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public static List<User> filter(List<User> users, Predicate<User> predicate) {
        List<User> results = new ArrayList<>();
        for (User user : users) {
            if (predicate.test(user)) {
                results.add(user);
            }
        }
        return results;
    }


    public static void main(String[] args) {
        filterUsersWithEvenId(Arrays.asList(new User(1, "a"), new User(2, "b")));
    }

    // 过滤ID为偶数的用户
    public static List<User> filterUsersWithEvenId(List<User> users) {
        return filter(users, new Predicate<User>() {
            @Override
            public boolean test(User user) {
                return user.id % 2 == 0;
            }
        });
    }

    // 过滤姓张的用户
    public static List<User> filterZhangUsers(List<User> users) {
        return filter(users, user -> user.name.startsWith("张"));
    }

    // 过滤姓王的用户
    public static List<User> filterWangUsers(List<User> users) {
        return filter(users, new Predicate<User>() {
            @Override
            public boolean test(User user) {
                return user.name.startsWith("王");
            }
        });
    }
    // 你可以发现,在上面三个函数中包含大量的重复代码。
    // 请尝试通过Predicate接口将上述代码抽取成一个公用的过滤器函数
    // 并简化上面三个函数
//    public static List<User> filter(List<User> users, Predi cate<User> predicate) {}

//    private interface 判断条件是否成立 {
//        boolean 这个用户是否满足条件(User user);
//    }
}

5

  • fileFilter.java
package com.github.hcsp.polymorphism;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;

public class FileFilter {
    public static void main(String[] args) throws IOException {
        Path projectDir = Paths.get(System.getProperty("user.dir"));
        Path testRootDir = projectDir.resolve("test-root");
        if (!testRootDir.toFile().isDirectory()) {
            throw new IllegalStateException(testRootDir.toAbsolutePath().toString() + "不存在!");
        }

        List<String> filteredFileNames = filter(testRootDir, ".csv");
        System.out.println(filteredFileNames);
    }

    /**
     * 实现一个按照扩展名过滤文件的功能
     *
     * @param rootDirectory 要过滤的文件夹
     * @param extension     要过滤的文件扩展名,例如 .txt
     * @return 所有该文件夹(及其后代子文件夹中)匹配指定扩展名的文件的名字
     */
    public static List<String> filter(Path rootDirectory, String extension) throws IOException {
        List<String> names = new ArrayList<>();
        Files.walkFileTree(rootDirectory, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println(file);
                if (file.getFileName().toString().endsWith(extension)) {
                    names.add(file.getFileName().toString());
                }
                return FileVisitResult.CONTINUE;
            }
        });
        return names;
    }
}

6

  • User.java
package com.github.hcsp.polymorphism;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class User {
    /** 用户ID,数据库主键,全局唯一 */
    private final Integer id;

    /** 用户名 */
    private final String name;

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    // 这里使用了一个NameCollector类,请尝试将它改写成匿名内部类
    // 使得代码更加集中,更加容易阅读
    public static List<String> collectNames(List<User> users) {
        NameCollector collector = new NameCollector() {
            private final List<String> names = new ArrayList<>();
            @Override
            public void accept(User user) {
                names.add(user.getName());
            }
            @Override
            public List<String> getNames() {
                return names;
            }
        };
        users.forEach(collector);
        return collector.getNames();
    }

    public static void main(String[] args) {
        List<User> users = Arrays.asList(new User(1, "a"), new User(2, "b"));
        System.out.println(collectNames(users));
    }

    public static class NameCollector implements Consumer<User> {
        @Override
        public void accept(User user) {

        }
        private final List<String> names = new ArrayList<>();

        public List<String> getNames() {
            return names;
        }

    }

}

7

  • Cat.java
package com.github.hcsp.polymorphism;

public class Cat {
    /** 猫的名字 */
    private final String name;

    public Cat(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
  • Home.java
package com.github.hcsp.polymorphism;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class Home {
    List<Cat> cats = new ArrayList<>();

    public List<String> getCatNames() {
        CatNameCollector collector = new CatNameCollector();
        cats.forEach(collector);
        return collector.getCatNames();
    }

    // 记录日志
    private void log(Cat cat) {
        System.out.println("Collecting cat " + cat.getName());
    }

    // 在这个类里会产生一个编译错误
    // 请思考一下为什么
    // 并将此类改写成非静态的内部类,以修复此问题
    class CatNameCollector implements Consumer<Cat> {

        // 编译器偷偷摸摸的帮你注入了一个外围类的实例/对象
        // private Home this$0;
        private List<String> catNames = new ArrayList<>();

        @Override
        public void accept(Cat cat) {
            log(cat);
            catNames.add(cat.getName());
        }

        private List<String> getCatNames() {
            return catNames;
        }
    }
}
  • Home2.java
package com.github.hcsp.polymorphism;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class Home2 {
    List<Cat> cats = new ArrayList<>();

    public List<String> getCatNames() {
        CatNameCollector collector = new CatNameCollector(this);
        cats.forEach(collector);
        return collector.getCatNames();
    }

    // 记录日志
    private void log(Cat cat) {
        System.out.println("Collecting cat " + cat.getName());
    }

    static class CatNameCollector implements Consumer<Cat> {
        // 在这个类里会产生一个编译错误
        // 请思考一下为什么
        // 不要将此类改写成非静态的内部类
        // 而是引入一个外围类的实例以调用外围类的实例方法
        private Home2 this$0;
        private List<String> catNames = new ArrayList<>();

        public CatNameCollector(Home2 this$0) {
            this.this$0 = this$0;
        }

        @Override
        public void accept(Cat cat) {
            this$0.log(cat);
            catNames.add(cat.getName());
        }

        private List<String> getCatNames() {
            return catNames;
        }
    }
}