美文网首页
Java 中的组合与继承

Java 中的组合与继承

作者: 丶沧月 | 来源:发表于2019-03-06 18:59 被阅读0次

    学习 JVM 的时候遇到了组合的概念,回想了下这是面向对象的知识,有点遗忘,所以写下这篇文章加深记忆。
    首先,继承和组合都是实现类复用的重要手段,但继承的坏处是会破坏封装性,而采用组合的方式能提供更好的封装性。

    继承(is-a) VS 组合(has-a)

    下面以组合和继承的综合例子来介绍它们的区别:

    要实现的目标:鸟(Bird)和狼(Wolf)都是动物(Animal),动物都有心跳(beat()),会呼吸(beat()),但是鸟会fly(fly()),狼会奔跑(run()),用java程序实现以上描述。

    
    class Animal {
        private void beat() {
            System.out.println("心脏跳动...");
        }
    
        public void breath() {
            beat();
            System.out.println("吸一口气,呼一口气,呼吸中...");
        }
    }
    
    // 继承Animal,直接复用父类的 breath() 方法
    class Bird extends Animal {
        // 创建子类独有的方法fly()
        public void fly() {
            System.out.println("我是鸟,我在天空中自由的飞翔...");
        }
    }
    
    // 继承Animal,直接复用父类的 breath() 方法
    class Wolf extends Animal {
        // 创建子类独有的方法 run()
        public void run() {
            System.out.println("我是狼,我在草原上快速奔跑...");
        }
    }
    
    public class InheritTest {
        public static void main(String[] args) {
            // 创建继承自 Animal 的 Bird 对象新实例 b
            Bird b = new Bird();
            // 新对象实例b可以breath()
            b.breath();
            // 新对象实例b可以fly()
            b.fly();
            Wolf w = new Wolf();
            w.breath();
            w.run();
            /*
             * ---------- 运行 Java 程序 ---------- 
             * 心脏跳动... 吸一口气,呼一口气,呼吸中... 
             * 我是鸟,我在天空中自由的飞翔...
             * 心脏跳动... 吸一口气,呼一口气,呼吸中... 
             * 我是狼,我在草原上快速奔跑...
             * 
             * 输出完毕 (耗时 0 秒) - 正常终止
             */
        }
    }
    
    // 使用组合方式实现目标
    class Animal {
        private void beat() {
            System.out.println("心脏跳动...");
        }
    
        public void breath() {
            beat();
            System.out.println("吸一口气,呼一口气,呼吸中...");
        }
    }
    
    class Bird {
        // 定义一个 Animal 成员变量,以供组合之用
        private Animal a;
    
        // 使用构造函数初始化成员变量
        public Bird(Animal a) {
            this.a = a;
        }
    
        // 通过调用成员变量的固有方法(a.breath())使新类具有相同的功能(breath())
        public void breath() {
            a.breath();
        }
    
        // 为新类增加新的方法
        public void fly() {
            System.out.println("我是鸟,我在天空中自由的飞翔...");
        }
    }
    
    class Wolf {
        private Animal a;
    
        public Wolf(Animal a) {
            this.a = a;
        }
    
        public void breath() {
            a.breath();
        }
    
        public void run() {
            System.out.println("我是狼,我在草原上快速奔跑...");
        }
    }
    
    public class CompositeTest {
        public static void main(String[] args) {
            // 显式创建被组合的对象实例 a1
            Animal a1 = new Animal();
            // 以 a1 为基础组合出新对象实例 b
            Bird b = new Bird(a1);
            // 新对象实例b可以 breath()
            b.breath();
            // 新对象实例b可以 fly()
            b.fly();
            Animal a2 = new Animal();
            Wolf w = new Wolf(a2);
            w.breath();
            w.run();
            /*
             * ---------- 运行Java程序 ---------- 
             * 心脏跳动... 吸一口气,呼一口气,呼吸中... 
             * 我是鸟,我在天空中自由的飞翔...
             * 心脏跳动... 吸一口气,呼一口气,呼吸中... 
             * 我是狼,我在草原上快速奔跑...
             * 
             * 输出完毕 (耗时 0 秒) - 正常终止
             */
        }
    }
    

    总结:

    继承和组合都可以实现代码的复用。

    • 如果是 is-a 关系,一个类想要对另外一个类暴露所有接口,继承看起来是更好的选择。
    • .如果是 has-a 关系,组合是更好的选择。

    相关文章

      网友评论

          本文标题:Java 中的组合与继承

          本文链接:https://www.haomeiwen.com/subject/tjrayqtx.html