gpt4 book ai didi

java - Java 中对象的动态类型转换

转载 作者:行者123 更新时间:2023-12-01 10:25:25 25 4
gpt4 key购买 nike

我有一个非常简单的包装类,它存储任何类及其类型的对象。现在我想检索该对象并对其执行一些操作。

这是我当前正在使用的代码的一个简短演示,但它太长了

Literal a = new Literal(new Complex(12, 0));
Literal b = new Literal(new Matrix(n, m));
Literal c = new Literal(new Variable("x"));
Literal d = new Literal(new Constant("y", 2.25));
Literal e = new Literal(new Real(2.5));

if (a.getType() == Literal.Type.COMPLEX)
{
Complex w = (Complex)a.getLiteral();
//Doing something
}
else if (a.getType() == Literal.Type.Matrix)
{
Matrix w = (Matrix)a.getLiteral();
//Doing something
}
else if (a.getType() == Literal.Type.Variable)
{
Variable w = (Variable)a.getLiteral();
//Doing something
}
else if (a.getType() == Literal.Type.Constant)
{
Constant w = (Constant)a.getLiteral();
//Doing something
}
else if (a.getType() == Literal.Type.Real)
{
Real w = (Real)a.getLiteral();
//Doing something
}

/* Same goes for all other Objects
* and I need to do this at least in
* 50 different places*/

我想到了三个解决方案,其中两个在这种情况下不起作用

  1. 制作Literal基类及其所有其他子类,但是 Literal不具有其子级将拥有的所有方法,并且会有很多子级。

  2. 制作Literal一个泛型类,但我想要存储的类型是可变的,因此我需要复制它们,并且 Java 不允许调用泛型上的任何方法。

  3. 这是有效的,但它增加了难以发现的错误的可能性。

这是我迄今为止的尝试:

import org.apache.commons.math3.linear.BlockRealMatrix;

public class Literal<T>
{
private final Object literal;

/*
* public enum Type
* {
* COMPLEX,
* VARIABLE,
* REAL,
* CONSTANT,
* MATRIX
* }
* private final Type type;
* */

public Literal(Complex c)//Complex class is mutable so make copy of passed object
{
this.literal = new Complex(c);
//this.type = Type.COMPLEX;
}

public Literal(Real d)//Real is not mutable so no need to make copy
{
this.literal = d;
//this.type = Type.REAL;
}

public Literal(BlockRealMatrix realMatrix)//BlockRealMatrix class is mutable so make copy of passed object
{
int m = realMatrix.getData().length;
int n = realMatrix.getData()[0].length;

BlockRealMatrix mat = new BlockRealMatrix(m, n);

for (int i = 0; i < m; i++)mat.setRow(i, realMatrix.getRow(i));
this.literal = mat;

//this.type = Type.MATRIX;
}

public T get()
{
return (T)this.literal;
}

/*
public Literal.Type getType()
{
return this.type;
}
*/

@Override
public String toString()
{
return this.literal.toString();
}
}

对于最后一种方法,可能的错误是:

package com.kmstudios.evaluator;

public class Main
{
public static void main(String[] args)
{
Literal<Real> a = new Literal<>(new Complex2(25, 36));//Accidently passed reference of Real instead of Complex
Literal<Complex2> b = new Literal<>(new Complex2(50, 36));

Literal<Complex2> c = new Literal<>(a.get().multiply(b.get()));
System.out.println(c.toString());//Expecting for Complex to print
}
}

class Real
{
private final Double d;

public Real(double d)
{
this.d = d;
}

public Real multiply(Real other)
{
return new Real(this.d * other.d);
}

public final double get()
{
return this.d;
}

@Override
public String toString()
{
return Double.toString(this.d);
}
}

class Complex2 extends Real
{
private double imaginary;

public Complex2(double real, double imaginary)
{
super(real);
this.imaginary = imaginary;
}

public Complex2 multiply(Complex2 o)
{
return new Complex2(this.get() * o.get() - this.imaginary * o.imaginary, this.get() * o.imaginary + this.imaginary * o.get());
}

public Complex2 multiply(double other)
{
return new Complex2(this.get() * other, this.imaginary * other);
}

@Override
public String toString()
{
StringBuilder builder = new StringBuilder("");
builder.append(this.get());

if (this.imaginary >= 0.0)builder.append("+");
builder.append(this.imaginary);

return builder.toString();
}
}

我注意到了这一点,但可能还有更多错误。我应该重新考虑我的数据结构?

我想知道是否有任何简单、不易出错、高效且简短的方法来做到这一点。

最佳答案

这是 Visitor pattern 的教科书案例.

public abstract class Literal<T extends Literal<T>> {
public abstract void accept(Visitor visitor);
// other elements
}

public class Variable extends Literal<Variable> {
public void accept(Visitor visitor) {
visitor.visit(this);
}
// other elements
}
public class Constant extends Literal<Constant> {
public void accept(Visitor visitor) {
visitor.visit(this);
}
// other elements
}

public interface Visitor {
public void visit(Variable variable);
public void visit(Constants variable);
// ... other types
}

public class DoSomethingVisitor implements Visitor{
public void visit(Variable variable) {
// do something with a variable
}
public void visit(Constant constant) {
// do something with a constant
}
// other methods.
}

简单来说,让类型系统帮你进行方法分派(dispatch);无需重新实现它。

关于java - Java 中对象的动态类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35378480/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com