zoukankan      html  css  js  c++  java
  • 关于java多继承和mixin实现(转)

    因为工作需要,最近在学习Java,跟Python相比,编码复杂度高了不少。Java语言语法多,一大堆概念,很些地方的设计与Python相比,实在是太糟糕,强烈建议改进,改进后能大大降低程序的复杂度。

    第一点:Java中定义了抽象类和接口,之所有定义接口这个概念,我感觉跟Java的类是单继承有一定关系,使用接口,可以一定程度上实现多继承的功能。而Python支持多继承,

    就不必有接口的概念。在Java中实现多继承和Mixin模式时,要复杂的多。而Python在语言设计上解决了这个问题。

    第二点:Java的函数不支持默认参数,而是通过overload的方式,这种方法的复杂度远比默认参数高。而Python,甚至C++都支持默认参数。

    原文:https://blog.csdn.net/wusj3/article/details/80360877

    接口是对动作的抽象,抽象类是对根源的抽象。
    抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。
    人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.


    Mixin 实质上是利用语言特性(比如 Ruby 的 include 语法、Python 的多重继承)来更简洁地实现组合模式

    以如下 Java 伪码为例,实现一个可复用的“打标签”组件(Taggable),并且应用到帖子(Post)模型上:
    import java.util.List;
    import java.util.ArrayList;
     
    interface Entity {
        public int getId();
        public int getKind();
    }
     
    interface Taggable {
        public void addTag(int tagId);
        public List<Integer> getTags();
    }
     
    class TaggableImpl implements Taggable {
        private Entity target;
     
        public TaggableImpl(Entity target) {
            this.target = target;
        }
     
        public void addTag(int tagId) {
            int id = target.getId();
            int kind = target.getKind();
            System.out.println("insert into ... values "
                    + id + ", "
                    + kind + ", "
                    + tagId + ")");
        }
     
        public ArrayList<Integer> getTags() {
            // query from database
            return new ArrayList<Integer>();
        }
    }
     
    class Post implements Entity, Taggable {
        public final static int KIND = 1001;
     
        private Taggable taggable;
        private int id;
        private String title;
     
        public Post(int id, String title) {
            this.id = id;
            this.title = title;
            this.taggable = new TaggableImpl(this);
        }
     
        public int getId() {
            return id;
        }
     
        public int getKind() {
            return KIND;
        }
     
        public void addTag(int tagId) {
            taggable.addTag(tagId);  // delegate
        }
     
        public ArrayList<Integer> getTags() {
            return taggable.getTags();  // delegate
        }
    }

    这里使用组合模式,在 TaggableImpl 中实现打标签的逻辑,然后让 Post 类和 TaggableImpl 类都实现 Taggable 接口,Post 类中创建一个 TaggableImpl 实例并在实现 Taggable 时将相应方法调用委托过去。

    如果在 Python 中应该怎么做呢?因为 Python 允许多重继承,所以“委托方法”的过程可以简化为直接将实现混入宿主类中:

    class TagMixin(object):
     
        def add_tag(self, tag_id):
            sql = ('insert into target_tagged'
                   ' (target_id, target_kind, tag_id, creation_time) '
                   'values (?, ?, ?, CURRENT_TIMESTAMP)')
            params = (self.ident, self.kind, tag_id)
            storage.execute(sql, params)
            storage.commit()
     
        def get_tags(self):
            sql = ('select tag_id, creation_time from target_tagged '
                   'where target_id = ? and target_kind = ?')
            params = (self.ident, self.kind)
            cursor = storage.execute(sql, params)
            return cursor.fetchall()
     
     
    class Post(Model, TagMixin):
     
        kind = 1001
     
        def __init__(self, ident, title):
            self.ident = ident
            self.title = title
     
        def __repr__(self):
            return 'Post(%r, %r)' % (self.ident, self.title)

    可以看出这里多重继承的用法是非常谨慎的:

    • TagMixin 类是单一职责的
    • TagMixin 类对宿主类(Post)一无所知,除了要求宿主类有 ident 和 kind 这两个属性(等价于 Java 中要求宿主类实现 Entity 接口)
    • 宿主类的主体逻辑不会因为去掉 TagMixin 而受到影响,同时也不存在超类方法调用(super)以避免引入 MRO 查找顺序问题

    所以这样比 Java 中的组合模式实现方式更加简洁。同时因为使用得当,钻石调用、MRO 查找顺序等多重继承的弊病也没有被踩到。当然,这种 Duck Type 的设计也比显式的接口约束对开发者有更高的要求,要求代码中无 interface 而开发者脑海中有清晰的 interface。

    Ruby 的 include 语法实现的 Mixin 也同理。

  • 相关阅读:
    [php learn] php 从头開始学习1
    Qt实现Windows远程控制
    [core java学习笔记][第十一章异常断言日志调试]
    网络安全-安全散列函数,信息摘要SHA-1,MD5原理
    Cardboard虚拟现实开发初步(二)
    C#中Stack&lt;T&gt;类的使用及部分成员函数的源代码分析
    编程算法
    读取spring配置文件的方法(spring读取资源文件)
    Spring中的事务管理详解
    配置spring事务管理的几种方式(声明式事务)
  • 原文地址:https://www.cnblogs.com/ajianbeyourself/p/12565315.html
Copyright © 2011-2022 走看看