【问题标题】:Groovy GString fails to interpolate a variable when referenced by an interfaceGroovy GString 在被接口引用时无法插入变量
【发布时间】:2021-08-16 18:36:49
【问题描述】:

总结

我有一个非常奇怪的情况,即 GString 错误地将变量内插为 null,即使该变量具有非空值集。请参阅下面的屏幕截图。但是,如果我通过变量的实际类而不是接口引用变量,它会正确插值。

PublicBinary是一个接口

interface PublicBinary {

    byte[] bytes
    String publicKey
    Person person
}

AdditionalPhoto 是实现PublicBinary 的具体类

class AdditionalPhoto implements PublicBinary, ToMap, DomainClass {

    byte[] bytes
    String publicKey
    String externalURL
    Person person
    AdditionalPhotoType additionalPhotoType
...
}

当我输入变量作为其接口时,插值失败,PublicBinary

但是当我将变量键入为它的实际类 AdditionalPhoto 而不是它的接口 PublicBinary 时,插值工作正常。

【问题讨论】:

  • “Groovy GString 在被接口引用时无法插入变量” - 仅供参考...您的代码似乎没有使用GString 插值。 photo.publicKey + ".jpg" 不涉及插值。

标签: grails groovy


【解决方案1】:

我无法重现您所描述的行为,但https://github.com/jeffbrown/tengritsandpapergstringinterpolation 的项目展示了一种可行的方法。

lib/src/main/groovy/tengritsandpapergstringinterpolation/PublicBinary.groovy

package tengritsandpapergstringinterpolation

interface PublicBinary {
    byte[] bytes
    String publicKey
    Person person
}

lib/src/main/groovy/tengritsandpapergstringinterpolation/AdditionalPublicBinary.groovy

package tengritsandpapergstringinterpolation

class AdditionalPublicBinary implements PublicBinary {
    byte[] bytes
    String publicKey
    String externalURL
    Person person
}

lib/src/main/groovy/tengritsandpapergstringinterpolation/Library.groovy

package tengritsandpapergstringinterpolation

class Library {
    String processByInterface(PublicBinary obj) {
        return "Public Key Is [${obj.publicKey}]"
    }

    String processByConcreteType(AdditionalPublicBinary obj) {
        return "Public Key Is [${obj.publicKey}]"
    }
}

lib/src/test/groovy/tengritsandpapergstringinterpolation/LibraryTest.groovy

package tengritsandpapergstringinterpolation

import spock.lang.Specification

class LibraryTest extends Specification {
    def "someLibraryMethod returns true"() {
        setup:
        def lib = new Library()
        def binary = new AdditionalPublicBinary(publicKey: 'My Key Value')

        expect:
        lib.processByConcreteType(binary) == 'Public Key Is [My Key Value]'
        lib.processByInterface(binary) == 'Public Key Is [My Key Value]'
    }
}

不寻常的一点是您在接口和实现中定义属性的方式。

【讨论】:

    【解决方案2】:

    问题是你的interface。这不是你的界面 打算,因为它没有为 你的财产。它定义了未初始化的、公共的、最终的属性。

    问题如下:

    interface I1 {
        String x
    }
    
    class X1 implements I1 {
    }
    
    println(new X1().x) // → null 
    

    如果你反编译“错误”的接口,你会看到发生了什么:

    public interface I {
      public static final java.lang.String x;
    }
    

    虽然“正确”的界面会符合您的期望:

    interface I2 {
        String getX()
    }
    
    class X2 implements I2 {
        String x
    }
    

    【讨论】:

    • "这不是一个合适的接口,因为它没有定义任何方法。" - 接口并非必须定义方法才能使其正确。许多接口没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多