用Java实现基于消息传递的OOP对象模型

0. 前言

首先声明,本文使用Java所实现OOP对象模型仅包含类、对象、访问控制(private、protected、public三种级别)、多继承(通过优先级来解决冲突)、方法调用等功能,不包含语法,仅用于说明,不可用于工程。

1. 实现效果

LClass aClass = define("A")
        .addField("name")
        .addField(PUBLIC, "age")
        .addField(PROTECTED, "color")
        .addField(PRIVATE, "id")
        .addMethod("showId", thisPointer -> args -> {
            System.out.println(thisPointer.get("id"));
            return null;
        })
        .addMethod(PUBLIC, "setId", thisPointer -> args -> {
            thisPointer.set("id", args[0]);
            return null;
        })
        .addMethod(PROTECTED, "changeNameAndPrint", thisPointer -> args -> {
            thisPointer.set("name", args[0]);
            System.out.println("name change to " + thisPointer.get("name"));
            return null;
        })
        .addMethod(PRIVATE, "changeColor", thisPointer -> args -> {
            thisPointer.set("color", args[0]);
            return null;
        }).end();

LObject aObject = aClass.newInstance();
System.out.println("a object:" + aObject);
aObject.set("name", "ZhouShenshen");
aObject.set("color", "ZhouShenshen");
aObject.set("id", "ZhouShenshen");
aObject.invoke("changeNameAndPrint", "XiaoMing");
aObject.invoke("setId", "1234");
aObject.invoke("showId");
System.out.println("a object:" + aObject);

LClass bClass = define("B", aClass)
        .addMethod("setName", thisPointer -> args -> {
            thisPointer.set("name", args[0]);
            return null;
        })
        .addMethod("setNameAndPrint", thisPointer -> args -> {
            thisPointer.invoke("changeNameAndPrint", args[0]);
            return null;
        })
        .end();
LObject bObject = newInstance(bClass);
bObject.invoke("changeNameAndPrint", "XiaoHua");
bObject.invoke("setNameAndPrint", "XiaoHua");
bObject.invoke("setName", "DingDing");

System.out.println("b object:" + bObject);

2. 代码

2.1 类的实现

类中包含了该类的名称、超类列表、成员集和方法集,定义的过程使用建造者模式实现,代码如下:

public class LClass {
    private final String name;
    private final List<LClass> superClasses;
    private final Map<String, LField> fieldMap;
    private final Map<String, LMethod> methodMap;

    public LClass(String name, List<LClass> superClasses, Map<String, LField> fieldMap, Map<String, LMethod> methodMap) {
        this.name = name;
        this.superClasses = superClasses;
        this.fieldMap = fieldMap;
        this.methodMap = methodMap;
    }

    List<LClass> getSuperClasses() {
        return superClasses;
    }

    public Map<String, LField> getFieldMap() {
        return fieldMap;
    }

    public String getName() {
        return name;
    }

    public Map<String, LMethod> getMethodMap() {
        return methodMap;
    }

    public LObject newInstance() {
        return new LObject(this);
    }

    public static LObject newInstance(LClass lClass) {
        return lClass.newInstance();
    }

    public static Builder define(String name, LClass... superClasses) {
        return new Builder(name, superClasses == null ? Collections.emptyList() : Arrays.asList(superClasses));
    }

    public static final class Builder {
        private final String name;
        private final List<LClass> superClasses;
        private final Map<String, LField> fieldMap = new HashMap<>();
        private final Map<String, LMethod> methodMap = new HashMap<>();

        Builder(String name, List<LClass> superClasses) {
            this.name = name;
            this.superClasses = superClasses;
        }

        public Builder addField(String name) {
            return addField(LModifier.PUBLIC, name);
        }

        public Builder addField(LModifier modifier, String name) {
            fieldMap.put(name, new LField(name, modifier));
            return this;
        }

        public Builder addMethod(String name, Function<LThisPointer, LMethod.MethodImplementor> method) {
            return addMethod(LModifier.PUBLIC, name, method);
        }

        public Builder addMethod(LModifier modifier, String name, Function<LThisPointer, LMethod.MethodImplementor> method) {
            methodMap.put(name, new LMethod(modifier, name, method));
            return this;
        }

        public LClass end() {
            return new LClass(name, superClasses, fieldMap, methodMap);
        }
    }
}

2.2 对象的实现

对象中包含该对象所属的类、直接超类的对象列表、成员域集合和This指针,提供方法调用和成员域读写的接口,并做访问控制

public class LObject {
    private final LClass objClass;
    private final List<LObject> parentObjects;
    private final Map<String, LField> fieldMap;
    private final LThisPointer thisPointer;

    public LObject(LClass objClass) {
        this.objClass = objClass;
        parentObjects = new ArrayList<>(objClass.getSuperClasses().size());
        for (LClass directSuperClass : objClass.getSuperClasses()) {
            parentObjects.add(directSuperClass.newInstance());
        }
        fieldMap = new HashMap<>();
        try {
            for (Map.Entry<String, LField> entry : objClass.getFieldMap().entrySet()) {
                fieldMap.put(entry.getKey(), entry.getValue().clone());
            }
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        thisPointer = new LThisPointer(this);
    }

    public LClass getObjClass() {
        return objClass;
    }

    List<LObject> getParentObjects() {
        return parentObjects;
    }

    Map<String, LField> getFieldMap() {
        return fieldMap;
    }

    public Object invoke(String name, Object... args) {
        Queue<LObject> objectQueue = new LinkedList<>();
        objectQueue.add(this);

        LMethod method = null;
        while (!objectQueue.isEmpty()) {
            LObject object = objectQueue.remove();
            method = object.objClass.getMethodMap().get(name);
            if (method != null) {
                break;
            } else {
                objectQueue.addAll(object.parentObjects);
            }
        }

        if (method == null) {
            throw new RuntimeException(new NoSuchMethodException(name));//note
        } else {
            if (method.getModifier() != LModifier.PUBLIC) {
                throw new RuntimeException(new IllegalAccessException(method.getModifier().toString()));
            } else {
                return method.invoke(thisPointer, args);
            }
        }
    }

    public Object get(String fieldName) {
        try {
            return findField(fieldName).getValue();
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void set(String fieldName, Object value) {
        try {
            findField(fieldName).setValue(value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private LField findField(String name) throws NoSuchFieldException, IllegalAccessException {
        Queue<LObject> objectQueue = new LinkedList<>();
        objectQueue.add(this);

        LField field = null;
        while (!objectQueue.isEmpty()) {
            LObject object = objectQueue.remove();
            field = object.fieldMap.get(name);
            if (field != null) {
                break;
            } else {
                objectQueue.addAll(object.parentObjects);
            }
        }

        if (field == null) {
            throw new NoSuchFieldException(name);
        } else {
            if (field.getModifier() != LModifier.PUBLIC) {
                throw new IllegalAccessException(field.getModifier().toString());
            } else {
                return field;
            }
        }
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder().append(objClass.getName()).append('[');

        for (LObject object : parentObjects) {
            builder.append(object.objClass.getName()).append("=>").append(object).append(',');
        }

        for (Map.Entry<String, LField> fieldEntry : this.fieldMap.entrySet()) {
            builder.append(fieldEntry.getKey()).append("->").append(fieldEntry.getValue().getValue()).append(',');
        }
        return builder.append(']').toString();
    }
}

2.3 this 指针的实现

This 指针提供的接口与对象类似,持有实际对象,但是对对象成员域和方法的访问控制不同,实现如下:

public class LThisPointer {
    private final LObject target;

    public LThisPointer(LObject target) {
        this.target = target;
    }

    public Object invoke(String name, Object... args) {
        LMethod method = target.getObjClass().getMethodMap().get(name);
        if (method != null) {
            return method.invoke(this, args);
        } else {
            Queue<LObject> objectQueue = new LinkedList<>(target.getParentObjects());
            while (!objectQueue.isEmpty()) {
                LObject object = objectQueue.remove();
                method = object.getObjClass().getMethodMap().get(name);
                if (method != null) {
                    break;
                } else {
                    objectQueue.addAll(object.getParentObjects());
                }
            }

            if (method == null) {
                throw new RuntimeException(new NoSuchMethodException(name));//note
            } else {
                if (method.getModifier() == LModifier.PRIVATE) {
                    throw new RuntimeException(new IllegalAccessException(method.getModifier().toString()));
                } else {
                    return method.invoke(this, args);
                }
            }
        }
    }

    public Object get(String fieldName) {
        try {
            return findField(fieldName).getValue();
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void set(String fieldName, Object value) {
        try {
            findField(fieldName).setValue(value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private LField findField(String name) throws NoSuchFieldException, IllegalAccessException {
        LField field = target.getFieldMap().get(name);
        if (field != null) {
            return field;
        } else {
            Queue<LObject> objectQueue = new LinkedList<>(target.getParentObjects());
            while (!objectQueue.isEmpty()) {
                LObject object = objectQueue.remove();
                field = object.getFieldMap().get(name);
                if (field != null) {
                    break;
                } else {
                    objectQueue.addAll(object.getParentObjects());
                }
            }

            if (field == null) {
                throw new NoSuchFieldException(name);
            } else {
                if (field.getModifier() == LModifier.PRIVATE) {
                    throw new IllegalAccessException(field.getModifier().toString());
                } else {
                    return field;
                }
            }
        }
    }
}

2.4 方法的实现

方法的定义通过柯里化的形式,将this指针与方法的实际参数分开传递给方法体,因此方法中仅包含修饰符、名称、以及方法实现,代码如下:

public class LMethod {
    private final LModifier modifier;
    private final String name;
    private final Function<LThisPointer, MethodImplementor> method;

    public LMethod(LModifier modifier, String name, Function<LThisPointer, MethodImplementor> method) {
        this.modifier = modifier;
        this.name = name;
        this.method = method;
    }

    public interface MethodImplementor {
        Object run(Object... args);
    }

    public LModifier getModifier() {
        return modifier;
    }

    public String getName() {
        return name;
    }

    public Object invoke(LThisPointer pointer, Object... args) {
        return method.apply(pointer).run(args);
    }
}

2.5 成员域的实现

成员域(Field)的实现更为简单,劲爆汗修饰符、名称和值。因为对象创建时需要克隆内容,所以添加了克隆的接口,代码如下:

public class LField implements Cloneable{
    private final String name;
    private Object value;
    private final LModifier modifier;

    public LField(String name, LModifier modifier) {
        this.name = name;
        this.modifier = modifier;
        value = null;
    }

    public String getName() {
        return name;
    }

    public LModifier getModifier() {
        return modifier;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    @Override
    protected LField clone() throws CloneNotSupportedException {
        return (LField) super.clone();
    }
}

2.6 访问修饰符

public enum LModifier {
    PUBLIC, PROTECTED, PRIVATE
}
发布了16 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zssrxt/article/details/103334687