Если вы попытаетесь использовать super
, вы получите сообщение об ошибке, что «абстрактный член не может быть доступен напрямую».Это относится к интерфейсам и классам;Вы не можете вызывать абстрактные методы без тела на super
.Это означает, что это не компилируется:
interface CrudRepo {
fun save()
fun saveAll()
}
interface CustomRepo : CrudRepo {
fun validate()
override fun save() {
validate()
super.saveAll()
}
}
Но измените интерфейс CrudRepo на это:
interface CrudRepo {
fun save()
fun saveAll(){
}
}
И это произойдет.
Если вы хотите абстрактный примервот, пожалуйста:
abstract class CrudRepo {
abstract fun save()
abstract fun saveAll()
}
class CustomRepo : CrudRepo() {
override fun saveAll() { }
override fun save() {
super.saveAll()
}
}
Вы получите то же сообщение об ошибке.Это потому, что вы не можете вызывать неосуществленные версии метода.Также давайте посмотрим на наследование.
interface CustomRepo : CrudRepo
class MyClass : CustomRepo
означает, что MyClass
является дочерним по отношению к CrudRepo и CustomRepo.И MyClass() as CustomRepo
, и MyClass() as CrudRepo
будут компилироваться.
Теперь, что это значит для вашей проблемы?
В CrudRepo
нет метода save
с точки зрения CustomRepo
.Он не реализован, и поэтому вы не можете вызвать его напрямую.Вызов super.saveAll()
, как я показал выше, означает call the saveAll method on my parent
.super
- очень строгое ключевое слово.Однако saveAll()
не переопределяется.Вы можете вызвать save
, но вы не можете вызвать его на суперинтерфейсе, потому что суперинтерфейс не имеет метода сохранения с телом .Последние три слова этого предложения здесь невероятно важны;поскольку метод, определенный в интерфейсе CrudBody, не имеет тела, его нельзя вызвать.
И, кроме того, поскольку вы переопределили метод, любые обращения к нему могут привести к рекурсии.Если вы сделаете это:
override fun save(){
save()
}
, он будет вызывать себя снова и снова, пока не произойдет сбой.См. Что такое StackOverflowError? .
Теперь, если у вас есть фактический класс:
class CustomRepoImpl : CustomRepo{
override fun saveAll() {
}
override fun save() {
super.save()
}
override fun validate() {
}
}
обратите внимание, как он вызывает super
;теперь он будет вызывать метод super в CustomRepo
.Однако это не обязательно.
И когда вы переопределяете save
в CustomRepo
, помните одну вещь: вы переопределяете метод CrudRepo.Любые дочерние классы больше не обязаны переопределять его вообще.Пример реализации, который я имел, скомпилировался бы без него.Причина, по которой saveAll
работает (без ключевого слова super
), заключается в том, что он является абстрактным и не ссылается на метод, из которого он вызывается.Смотрите ссылку StackOverflowError.Если вы вызываете переопределенный метод, вызывается метод в дочернем классе, если только метод не вызывается на super
.
И вы не можете вызвать super
для методов без тела в суперклассе или интерфейсе, потому что язык не знает, на что вы указываете, потому что там ничего нет.
TL; DR: Вы не можете вызвать супер метод абстрактного / безличного метода.saveAll
относится к первой реализации метода или суперклассу, если он определен в дочернем элементе.Вызов save
приведет к ошибке StackOverflowError.