简体   繁体   中英

Lazy initialization of Kotlin class property won't compile

I am not entirely sure that what I think is the problem actually it. But I am trying to use lazy as a delegate and I am getting compiler errors

data class Geocode(var latitude: Double, var longitude: Double) : Comparable<Geocode> {


    override fun compareTo(other: Geocode): Int {
        var result = this.latitude.compareTo(other.latitude)
        if (result == 0)
            result = this.longitude.compareTo(other.longitude)
        return result
    }
}

data class HubKt(val position:Geocode) {
}

data class Example(val hubs:Collection<HubKt>) {

    val bounds:Any by lazy {
        object {
            val ne: this.hubs.map { h -> h.position }.max()
            val sw: this.hubs.map { h -> h.position }.min()
        }

    }
}

if this were java, I would want the bounds function to return a map:

public Map<String,Geocode> getBounds() {
        Geocode ne = geos.stream().max(Geocode::compareTo).get();
        Geocode sw = geos.stream().min(Geocode::compareTo).get();
        return ImmutableMap.of("ne",ne,"sw",sw);
}

I think the problem is not using the correct this . I tried this@Authenticate and it's a no go. Hell, I might even be over complicating it. Thanks for the insight.

Based on the current code in the question:

data class Bounds(val ne: Geocode, val sw: Geocode)

data class Example(val hubs:Collection<HubKt>) {
    val bounds: Bounds by lazy {
        Bounds(hubs.map { it.position }.max()!!, 
               hubs.map { it.position }.min()!!)
    }
} 

Otherwise in your answer you won't be able to access ne and sw in your anonymous descendant of Any that you create via the object expression. You need a typed response such as the Bounds class or a Map (which would be icky). And also in your version they could be null. If you know you have at least one value in the list you can use !! to assert you know the result of max or min will not be null.

You can do this without the copy created by the map with this change:

data class Example(val hubs:Collection<HubKt>) {
    val bounds: Bounds by lazy {
        Bounds(hubs.maxBy { it.position }!!.position, 
               hubs.minBy { it.position }!!.position)
    }
}    

Or if you want nulls as a possible bounds use the ?. safe operator instead of !!. and change the Bounds class to allow null :

data class Bounds(val ne: Geocode?, val sw: Geocode?)

data class Example(val hubs:Collection<HubKt>) {
    val bounds by lazy {
        Bounds(hubs.maxBy { it.position }?.position, 
               hubs.minBy { it.position }?.position)
    }
}

Notice in the last example I dropped the type from val bounds: Bounds because it is optional and type inference will figure it out just fine.

Ok, I solved the problem: 2 fold

Syntax error as "unknown symbol"? I needed = and not : (DOH!)

  val bounds:Any by lazy {
        object {
            val ne = hubs.map { h -> h.position }.max()
            val sw = hubs.map { h -> h.position }.min()
        }

    }

Lombok: position in Hub has it's getter generated by Lombok:

@Getter
@Setter
private Geocode position = new Geocode(50.0,50.0);

Change to:

@Setter
private Geocode position = new Geocode(50.0,50.0);

public Geocode getPosition() {
    return position;
}

Ultimately this was an integration issue. sigh

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM