Kotlin: ожидание объявления menber, когда кажется, что я уже сделал

#java #kotlin #lambda #kotlin-coroutines

#java #kotlin #лямбда #kotlin-сопрограммы

Вопрос:

Я нашел несколько вопросов с тем же сообщением об ошибке, но, насколько я вижу, я объявил его правильно.

Вот весь код в Kotlin:

 package com.mybank.service

import org.reactivestreams.Publisher
import com.mongodb.client.result.InsertOneResult
import com.mongodb.reactivestreams.client.MongoClients
import com.mongodb.reactivestreams.client.MongoClient
import com.mongodb.reactivestreams.client.MongoCollection
import com.mongodb.reactivestreams.client.MongoDatabase
import java.util.Arrays
import org.bson.Document

class test {


    //MongoClient mongoClient = MongoClients.create();
    var mongoClient: MongoClient = MongoClients.create("mongodb://root:q@localhost:27017")
    var database: MongoDatabase = mongoClient.getDatabase("mydb")
    var collection: MongoCollection<Document> = database.getCollection("mycollection")

    var doc: Document = Document("name", "MongoDB")
            .append("type", "database")
            .append("count", 1)
            .append("versions", Arrays.asList("v3.2", "v3.0", "v2.6"))
            .append("info", Document("x", 203).append("y", 102))


    //publisher decalred and initialized
    var publisher: Publisher<InsertOneResult> = collection.insertOne(doc)

    publisher *** why publisher isn't initialized yet???
  

Он работает в Java таким образом

 imports ommited, same as above
public class App {
    public static void main(String[] args) throws Throwable {

        //MongoClient mongoClient = MongoClients.create();
        MongoClient mongoClient = MongoClients.create("mongodb://root:q@localhost:27017");
        MongoDatabase database = mongoClient.getDatabase("mydb");
        MongoCollection<Document> collection = database.getCollection("mycollection");

        Document doc = new Document("name", "MongoDB")
                .append("type", "database")
                .append("count", 1)
                .append("versions", Arrays.asList("v3.2", "v3.0", "v2.6"))
                .append("info", new Document("x", 203).append("y", 102));


        Publisher<InsertOneResult> publisher = collection.insertOne(doc);

        publisher.subscribe(new Subscriber<InsertOneResult>() {
            @Override
            public void onSubscribe(final Subscription s) {
                s.request(1);  // <--- Data requested and the insertion will now occur
            }

            @Override
            public void onNext(final InsertOneResult result) {
                System.out.println("Inserted: "   result);
            }

            @Override
            public void onError(final Throwable t) {
                System.out.println("Failed");
            }

            @Override
            public void onComplete() {
                System.out.println("Completed");
            }
        });

        //all examples
        collection.countDocuments()
                .subscribe(new SubscriberHelpers.PrintSubscriber<Long>("total # of documents after inserting "
                          " is: %s"));

        collection.find(eq("name", "MongoDB")).first().subscribe(new SubscriberHelpers.PrintDocumentSubscriber());

        Thread.sleep(1000);

    }

}
  

Сообщение об ошибке:

IntelliJ

Я не программирую для Android, и вот build.gradle хотя я думаю, что это не имеет значения

 plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.72"
    id "org.jetbrains.kotlin.kapt" version "1.3.72"
    id "org.jetbrains.kotlin.plugin.allopen" version "1.3.72"
    id "application"
    id 'com.google.protobuf' version '0.8.13'
}

version "0.2"
group "account-control"

repositories {
    mavenLocal()
    jcenter()
}

configurations {
    // for dependencies that are needed for development only
    developmentOnly
}

dependencies {
    kapt(enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion"))
    kapt("io.micronaut:micronaut-inject-java")
    kapt("io.micronaut:micronaut-validation")

    implementation(enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion"))
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
    implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
    implementation("io.micronaut:micronaut-runtime")
//    implementation("io.micronaut.grpc:micronaut-grpc-runtime")
    implementation("io.micronaut.grpc:micronaut-grpc-server-runtime:$micronautGrpcVersion")
    implementation("io.micronaut.grpc:micronaut-grpc-client-runtime:$micronautGrpcVersion")
    implementation("io.grpc:grpc-kotlin-stub:${grpcKotlinVersion}")

    //Kafka
    implementation("io.micronaut.kafka:micronaut-kafka")

    //vertx
    implementation("io.micronaut.sql:micronaut-vertx-mysql-client")
    //implementation("io.micronaut.configuration:micronaut-vertx-mysql-client")
    compile 'io.vertx:vertx-lang-kotlin:3.9.4'

    //mongodb
    implementation("org.mongodb:mongodb-driver-reactivestreams:4.1.1")

    runtimeOnly("ch.qos.logback:logback-classic:1.2.3")
    runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8")

    kaptTest("io.micronaut:micronaut-inject-java")

    testImplementation enforcedPlatform("io.micronaut:micronaut-bom:$micronautVersion")
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.0")
    testImplementation("io.micronaut.test:micronaut-test-junit5")
    testImplementation("org.mockito:mockito-junit-jupiter:2.22.0")

    testRuntime("org.junit.jupiter:junit-jupiter-engine:5.3.0")
    testRuntime("org.jetbrains.spek:spek-junit-platform-engine:1.1.5")
}

test.classpath  = configurations.developmentOnly

mainClassName = "account-control.Application"

test {
    useJUnitPlatform()
}

allOpen {
    annotation("io.micronaut.aop.Around")
}

compileKotlin {
    kotlinOptions {
        jvmTarget = '11' 
        //Will retain parameter names for Java reflection
        javaParameters = true 
    }
}
//compileKotlin.dependsOn(generateProto)

compileTestKotlin {
    kotlinOptions {
        jvmTarget = '11' 
        javaParameters = true 
    }
}

tasks.withType(JavaExec) {
    classpath  = configurations.developmentOnly
    jvmArgs('-XX:TieredStopAtLevel=1', '-Dcom.sun.management.jmxremote')
}

sourceSets {
    main {
        java {
            srcDirs 'build/generated/source/proto/main/grpc'
            srcDirs 'build/generated/source/proto/main/grpckt'
            srcDirs 'build/generated/source/proto/main/java'
        }
    }
}

protobuf {
    protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
    plugins {
        grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
        grpckt { artifact = "io.grpc:protoc-gen-grpc-kotlin:${grpcKotlinVersion}" }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
            grpckt {}
        }
    }
}
  

*** отредактировано

 package com.mybank.service

import org.reactivestreams.Publisher
import com.mongodb.client.result.InsertOneResult
import com.mongodb.reactivestreams.client.MongoClients
import com.mongodb.reactivestreams.client.MongoClient
import com.mongodb.reactivestreams.client.MongoCollection
import com.mongodb.reactivestreams.client.MongoDatabase
import java.util.Arrays
import org.bson.Document
import javax.inject.Singleton

class test {


    //MongoClient mongoClient = MongoClients.create();
    var mongoClient: MongoClient = MongoClients.create("mongodb://root:q@localhost:27017")
    var database: MongoDatabase = mongoClient.getDatabase("mydb")
    var collection: MongoCollection<Document> = database.getCollection("mycollection")

    var doc: Document = Document("name", "MongoDB")
            .append("type", "database")
            .append("count", 1)
            .append("versions", Arrays.asList("v3.2", "v3.0", "v2.6"))
            .append("info", Document("x", 203).append("y", 102))


    //publisher decalred and initialized
    var publisher: Publisher<InsertOneResult> = collection.insertOne(doc)
}
  

затем в другом классе

 @Singleton
class TransactionService(){

    @Inject
    lateinit var test: test

    fun postDebitTransaction(debit: String) : String{

        test.publisher.subscribe(
                object x: Subscriber<InsertOneResult> {
                    override fun onSubscribe(s: Subscription) {
                        s.request(1) // <--- Data requested and the insertion will now occur
                    }

                    override fun onNext(result: InsertOneResult) {
                        println("Inserted: $result")
                    }

                    override fun onError(t: Throwable) {
                        println("Failed")
                    }

                    override fun onComplete() {
                        println("Completed")
                    }
                })

        return "posted"
    }
}
  

И я получаю

Несоответствие типов. Требуется: подписчик<в InsertOneResult!>!

Я совершенно уверен, что я делаю какую-то глупую ошибку в Kotlin

Комментарии:

1. каков возвращаемый тип collection.insertOne(doc) ?

2. углубляясь с помощью control click, я вижу Publisher<InsertOneResult> insertOne(TDocument var1); поэтому я понимаю, что возвращаемый тип — Publisher . И Control щелчок в издательство я вижу публичных издатель интерфейс <T> { общественного недействительными подписаться(подписчика<? супер T> s); }

3. Хм… api.mongodb.com/java/3.0/com/mongodb/client/…

Ответ №1:

Компилятор не сообщает вам, что элемент не инициализирован, он сообщает вам, что вам не разрешено вызывать функции в теле класса, если они не являются частью объявления члена.

например

 class Foo {
    // not allowed
    3.toString()
}

class Bar {
    // prefectly fine
    val three = 3.toString()
}
  

Java имеет такое же поведение.
Почему ваш пример Java работает, потому что ваш код находится внутри main метода, а не тела класса.

Комментарии:

1. Спасибо. Я не понял вашу точку зрения. Если я правильно понял, то же самое вы сделали с val three = 3.toString() Я выполнил с помощью var publisher: Publisher<InsertOneResult> = collection.insertOne(документ)

2. Да, но вам не разрешено вызывать publisher.subscribe тело класса

3. Я внедряю этот класс в другой одноэлементный класс: @Inject lateinit var test: test, а затем я могу, по крайней мере, test.publisher.subscribe . Но затем я получаю несоответствие типов. Требуется: подписчик<в InsertOneResult!>!. Я добавлю весь приведенный выше код

4. Пожалуйста, можете ли вы просмотреть приведенный выше код и сказать мне, что я делаю не так в Kotlin?

5. @JimC проблема с вашим кодом заключается в том, что вы не объявили main() функцию в своем коде Kotlin