Java 基类的toString()实现的动态替换

Java 基类的toString()实现的动态替换,java,Java,我有一个a班和一个a班 public String toString() { } 公共字符串toString(){ } 方法 它被编译。 另外,我有几个方法的实现作为一个方法体。 此实现使用A的字段 我希望能够动态替换toString()方法的内容 有这样或那样的实现。这里的要点是,我需要在实现中使用A的字段 我必须说,我不能创建A的子类。我必须只使用这个类 正如我所猜测的,每个实现都必须在第一次使用之前编译。 但人们会怎么做呢 最简单的解决方案可能是在调用某个或某个方法之前使用一个标志变量并

我有一个a班和一个a班

public String toString() { } 公共字符串toString(){ } 方法

它被编译。 另外,我有几个方法的实现作为一个方法体。 此实现使用A的字段

我希望能够动态替换toString()方法的内容 有这样或那样的实现。这里的要点是,我需要在实现中使用A的字段

我必须说,我不能创建A的子类。我必须只使用这个类

正如我所猜测的,每个实现都必须在第一次使用之前编译。 但人们会怎么做呢


最简单的解决方案可能是在调用某个或某个方法之前使用一个标志变量并对其进行分析,甚至将所有内容放入toString和use开关中。
但是,如果A对其实现本身一无所知呢?它们可以解耦吗?A类及其toString实现?

我不明白这样做的意义,也不明白“动态替换”的确切含义,但您可以向A添加一个附加字段,用于切换实现。大致如下。然后,您可以通过更改此模式变量“动态”切换到不同的实现

public String toString() {
  switch(mode) {
    case 1: return toStringImplementation1();
    case 2: return toStringImplementation2();
    /* ... */
    default: return super.toString();
  }
}

至于你关于脱钩的后续问题:当然,这是可能的。但是,您说过实现直接依赖于A的字段,您可能不想将这些字段公开。我也不认为将实现解耦为内部类而不是普通方法有什么好处,但我仍然不知道您要实现什么。

我不明白这样做的意义,也不明白您所说的“动态替换”到底是什么意思,但是,您可以向添加一个附加字段,用于切换实现。大致如下。然后,您可以通过更改此模式变量“动态”切换到不同的实现

public String toString() {
  switch(mode) {
    case 1: return toStringImplementation1();
    case 2: return toStringImplementation2();
    /* ... */
    default: return super.toString();
  }
}

至于你关于脱钩的后续问题:当然,这是可能的。但是,您说过实现直接依赖于A的字段,您可能不想将这些字段公开。我也不认为将实现解耦为内部类而不是简单的方法有什么好处,但我仍然不知道您想要实现什么。

我猜理论上您可以使用
toString()
方法的不同实现创建多个名为
A
的类,然后用不同的类加载器动态加载它们,等等。然而,从JVM的角度来看,它们将是不同的类,并且您无法以不同的方式说服JVM。这样你就不会“赢”了


更实际的方法可能是这样的:

class A {
    Formatter f;
    A(Formatter f) {
        this.f = f;
    }
    ...
    @Override 
    public String toString() {
        return f.format(this);
    }
}

并编写大量类来实现
格式化程序
接口。

我猜理论上,您可以使用
toString()
方法的不同实现创建多个名为
A
的类,然后使用不同的类加载器动态加载它们。然而,从JVM的角度来看,它们将是不同的类,您无法以不同的方式说服JVM。这样你就不会“赢”了


更实际的方法可能是这样的:

class A {
    Formatter f;
    A(Formatter f) {
        this.f = f;
    }
    ...
    @Override 
    public String toString() {
        return f.format(this);
    }
}
并编写许多类来实现格式化程序接口。

如何使用

decorator模式是一种设计模式,允许向现有对象调用添加新的/附加的行为

(虽然我不确定这是否符合您可以或不能对A进行的更改)

编辑:如果您可以明确地只使用A的字段(而不是字段访问器(getter)方法),那么Decorator模式可能无法工作。从问题中很难判断是否是这种情况。

如何使用

decorator模式是一种设计模式,允许向现有对象调用添加新的/附加的行为

(虽然我不确定这是否符合您可以或不能对A进行的更改)


编辑:如果您可以明确地只使用A的字段(而不是字段访问器(getter)方法),那么Decorator模式可能无法工作。从这个问题很难判断情况是否如此。

这是家庭作业吗?如果是这样,你应该给它贴上这样的标签

提供最佳解决方案的方法取决于您想要实现的目标,如果您需要对象的多个字符串表示,您可以引入多个版本的toString,如:

public String toString() {
}

public String toXmlString() {
}

public String toHumanFriendlyString() {
}
另一方面,如果在对象中实现了上述方法,并且希望设置输出格式,则可以使用输出类型:

public String toString() {
    switch (outputType) {
    default:
         return "Unknown output type for: " + toDebugString();
    case TYPE_DEBUG:
         return toDebugString();
    case TYPE_XML:
         return toXmlString();

}
如果需要从代码的其他部分设置实现,可以使用插件模式:

interface Stringable {
    String toString(A a);
}

class A {

    Stringable impl = this;

    void setStringable(Stringable s) {
         impl = s;
    }

    String toString() {
         return impl.toString(this);
    }

    String toString(A a) {

          return "A a";
    }
}

这是家庭作业吗?如果是这样,你应该给它贴上这样的标签

提供最佳解决方案的方法取决于您想要实现的目标,如果您需要对象的多个字符串表示,您可以引入多个版本的toString,如:

public String toString() {
}

public String toXmlString() {
}

public String toHumanFriendlyString() {
}
另一方面,如果在对象中实现了上述方法,并且希望设置输出格式,则可以使用输出类型:

public String toString() {
    switch (outputType) {
    default:
         return "Unknown output type for: " + toDebugString();
    case TYPE_DEBUG:
         return toDebugString();
    case TYPE_XML:
         return toXmlString();

}
如果需要从代码的其他部分设置实现,可以使用插件模式:

interface Stringable {
    String toString(A a);
}

class A {

    Stringable impl = this;

    void setStringable(Stringable s) {
         impl = s;
    }

    String toString() {
         return impl.toString(this);
    }

    String toString(A a) {

          return "A a";
    }
}

这听起来很奇怪。你能解释一下为什么要这样做吗?@Stephen C嗯,我的框架生成了一个类型为的类。它使我能够修改它的toString()方法。然后根据toString()返回的内容获取对象并进一步进行处理。理论上,如果我需要“某物”的多个实例,那么我需要一个类型的多个对象。但是我发现,如果我能够替换toString()方法,那么我只需要一个对象就可以做到这一点。这听起来可能很奇怪,但可能会给我带来一些好处。@EugeneP-事实是