Можно ли повысить тип получателя свойств?
Например, внутри объявления класса у меня есть val member = Implementation(), но я хочу, чтобы геттер общественный возвращал ссылку, набранную с помощью SomeInterface, при условии, что Implementation является подтипом SomeInterface, тогда как внутри объявления класса этот тип будет использоваться как экземпляр Implementation.
Вот полный пример на Java, чтобы дать ясную картину:
public class MyViewModel extends ViewModel {
private final MutableLiveData<Settings> settings = new MutableLiveData<>();
public LiveData<Settings> getSettings() {
return settings;
}
public void updateSettings() {
settings.setValue(new Settings());
}
}
Здесь это «свойство» видно снаружи как LiveData (супертип MutableLiveData), но внутри класса его можно использовать как MutableLiveData.
Я бы сказал, это звучит естественно, но похоже, что Котлин этого не допускает. Я что-то упускаю? Или создание private val _private = Implementation() и val _public: SomeInterface = _private или реализация собственного метода с семантикой получателя и измененным именем с возвращаемым типом SomeInterface - единственный способ добиться этого?
Конечно, я просто говорю об удобстве, если бы я мог, например, написать что-нибудь вроде val someObject = Implementation() и get(): SomeInterface





Я думаю (если я правильно понял ваш вопрос), что явное объявление типа member сделает то, что вы хотите, например
interface SomeInterface
class Implementation : SomeInterface
class Test {
val member: SomeInterface = Implementation()
}
ОБНОВИТЬ: после обновления вопроса, чтобы уточнить, что в тестовом классе member должен иметь тип Implementation, а не SomeInterface ...
Я не думаю, что то, что вы пытаетесь сделать, можно сделать без переменной-члена, как вы предлагаете в своем вопросе. Однако, если у вас есть базовый класс, который определяет, каким должен быть ваш member, вы может как бы делаете то, что хотите:
interface SomeInterface
class Implementation : SomeInterface
abstract class Super {
abstract val member: SomeInterface
}
class Test : Super() {
override val member = Implementation()
// declared as Implementation, but does correctly implement superclass which wants this to be a SomeInterface.
// In this class, member is of type Implementation.
}
fun test() {
val test1 = Test()
val member1 = test1.member // member1 is an Implementation object
val test2: Super = Test()
val member2 = test2.member // member2 is a SomeInterface object
}
Выше показано, что у вас может быть member, который доступен в вашем классе как Implementation, но виден за пределами класса как SomeInterface. Но только если, когда вы работаете с ним вне класса, вы работаете с ним как с экземпляром суперкласса, который определяет member как имеющий тип SomeInterface.
Извините, я обновил вопрос: это не то, что я хочу, потому что внутри класса Test я не могу рассматривать member как тип Implementation
Он наверняка будет работать с трюком раннего связывания и ковариации, но вопрос заключается в повышении без наследования и объявления абстрактного метода. Но в любом случае вы подтвердили, что это невозможно. Спасибо!
Внутри класса вы не работаете со свойством. Вы используете поле. Я имею в виду, что вы не вызываете
getSettings().setValue(...), который не компилирует IMO, но вы вызываетеsettings.setValue(...), вы можете это сделать, потому чтоsettingsотносится к типуMutableLiveData, аgetSettings()- нет. У меня тот же вариант использования, что и у вас, сLiveData, и я использую комбинацию переменных_privateиpublic, как вы предлагаете в своем сообщении.