Неразрешенная ссылка на функцию в пользовательском классе - PullRequest
0 голосов
/ 29 апреля 2018

Я не могу решить, казалось бы, тривиальную проблему. Моя проблема, вероятно, заключается в отсутствии у меня опыта (и понимания) языка котлин. Тем не менее, мне понадобится помощь с этим.

Я создал собственный класс, содержащий пользовательскую функцию. Это кажется достаточно простым, но я продолжаю получать ошибку «неразрешенная ссылка», когда пытаюсь использовать эту функцию.

Этот фрагмент кода примера воспроизводит ошибку:

abstract class Test {

    private var test: Test? = null

    fun getBla(): Test? {
        return test
    }

    fun shout() {
        println("Whaaaaa!")
    }

}

fun main(args: Array<String>) {
    val tst = Test.getBla()
    tst.shout()
}

Ошибка читает Unresolved reference: getBla

Класс может не иметь такого большого смысла, но он предназначен для имитации структуры фактического класса, который я использую в своем приложении.

Я чувствую, что совершаю ужасную ошибку новичка. Я искал документацию по Stackoverflow и Kotlin, но не могу найти решение.

Я протестировал приведенный выше код на try.kotlinlang.org , просто заменив пример "hello world".

#### РЕДАКТИРОВАТЬ

Боюсь, контекст приложения, которое я пытаюсь создать, может быть важен в конце концов. Я пытаюсь реализовать базу данных Room, но самый понятный учебник, который я смог найти, касается Java, поэтому я пытаюсь перевести, и это заставляет меня сталкиваться с проблемами.

Это страница, на которой я сейчас следую: База данных комнат . Мне нужно, чтобы класс «Test» здесь был единичным, для этого и было предназначено фактическое содержимое «getBla ()».

Чтобы перейти к актуальной проблеме, вот как выглядит настоящий класс:

@Database(entities = [(Box::class)], version = 1)
abstract class BoxRoomDatabase : RoomDatabase() {
    abstract fun boxDao(): BoxDao

    private var boxRoomDatabase: BoxRoomDatabase? = null

    fun getDatabase(context: Context): BoxRoomDatabase? {
        if (boxRoomDatabase == null) {

            //Double colon allows to get the Java class instead of a KClass, which is not equivalent
            synchronized<Unit>(BoxRoomDatabase::class.java) {
                boxRoomDatabase = Room.databaseBuilder(context.applicationContext,
                        BoxRoomDatabase::class.java, "box_database")
                        .build()
            }
        }
        return boxRoomDatabase
    }

}

Итак, BoxRoomDatabase должен быть синглтоном. Проблема возникает из-за автоматического перевода кода Java на Kotlin. Кажется, эта ситуация слишком сложна для этого. Я пытался найти ответ, ища различные комбинации «Kotlin», «Singleton» и «абстрактный метод». В конце концов я наткнулся на этот блог: Kotlin singletons с аргументом . Что мне было нужно, так это синглтон, который принимает аргумент, что, очевидно, не было тривиальной вещью в Котлине. В этом блоге объясняется, как реализовать такую ​​конструкцию.

Мой код теперь по крайней мере компилируется, если он действительно делает то, что я хочу, я узнаю позже. Моя текущая реализация выглядит примерно так:

SingletonHolder.kt (для построения синглетонов с аргументами)

open class SingletonHolder<out T, in A>(creator: (A) -> T) {
    private var creator: ((A) -> T)? = creator
    @Volatile private var instance: T? = null

    fun getInstance(arg: A): T {
        val i = instance
        if (i != null) {
            return i
        }

        return synchronized(this) {
            val i2 = instance
            if (i2 != null) {
                i2
            } else {
                val created = creator!!(arg)
                instance = created
                creator = null
                created
            }
        }
    }
}

BoxRoomDatabase.kt

import android.arch.persistence.room.RoomDatabase
import android.arch.persistence.room.Database
import android.content.Context
import android.arch.persistence.room.Room


@Database(entities = [(Box::class)], version = 1)
abstract class BoxRoomDatabase : RoomDatabase() {
    abstract fun boxDao(): BoxDao

    private var boxRoomDatabase: BoxRoomDatabase? = null

    companion object : SingletonHolder<BoxRoomDatabase, Context>({
        Room.databaseBuilder(it.applicationContext,
                BoxRoomDatabase::class.java, "box_database")
                .build()
    })

}

BoxRepository.kt

class BoxRepository internal constructor(application: Application) {

    private val mBoxDao: BoxDao
    private val mAllBoxes: LiveData<List<Box>>

    init {
        mBoxDao = BoxRoomDatabase.getInstance(application).boxDao()
        mAllBoxes = mBoxDao.getAllBoxes()
    }

    fun getAllBoxess(): LiveData<List<Box>> {
        return mAllBoxes
    }

    fun insert(box: Box) {
        InsertAsyncTask(mBoxDao).execute(box)
    }

    private class InsertAsyncTask internal constructor(private val mAsyncTaskDao: BoxDao) : AsyncTask<Box, Void, Void>() {

        override fun doInBackground(vararg params: Box): Void? {
            mAsyncTaskDao.insert(params[0])
            return null
        }
    }
}

Даже если это компилируется, это может быть не лучшим способом сделать это. Если у кого-то есть какие-либо данные о структуре приведенного выше кода, не стесняйтесь поделиться своими данными.

1 Ответ

0 голосов
/ 29 апреля 2018
val tst = Test.getBla()

Это, вероятно, говорит, что вы пытаетесь вызвать getBla() на Test.Companion, что означает, что вы пытаетесь вызвать его как статический метод (Java).

abstract class Test {
    companion object {
       fun getBla(): Test? = ...

Но вы не пытаетесь это сделать, поэтому вам, вероятно, следует создать экземпляр класса, для которого вы вызываете свой метод. Это абстрактный класс, поэтому вам потребуется его анонимная реализация.

fun main(args: Array<String>) {
    val test = object: Test() {}
    val bla = test?.getBla()
    bla?.shout()
}

Технически вам также не нужен fun getBla(), потому что вы можете просто использовать свойство с приватным сеттером.

var bla: Test? = null
    private set

Теперь вы можете просто получить к нему доступ как

val bla = test.bla
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...