Using both Abstract classes and interfaces at the ...
# android
v
Using both Abstract classes and interfaces at the same time
I have recently discovered that the following is possible in Kotlin:
Copy code
interface Movable {
    fun move()
}

abstract class Animal {
    abstract fun eat()
    fun sleep() {
        println("Zzz...")
    }
}

class Dog : Animal(), Movable {
    override fun move() {
        println("Dog is walking")
    }
    
    override fun eat() {
        println("Dog is eating")
    }
}
Specifically, the class
Dog
implementing both an
Interface
and inheriting from an
Abstract
class at the same time. Is this considered a good practice, particularly in the
Android
ecosystem? I have 2 repositories that implement 2 methods uniquely but share 1 identical method and this seems to be like a good solution?
I see, however, that a base class can implement an interface and through
abstract
keyword redelegate and enforce its implementation details to its subclasses:
Copy code
interface MusicPlayerRepository {
    fun play()
    fun search()
}

// Case 1: Base class implements the interface
abstract class BaseMusicPlayerRepository : MusicPlayerRepository {
    // Must either:
    // a) Implement all interface methods
    override fun play() {
        // Common implementation for playing audio
    }
    
    // b) Or mark them as abstract
    abstract override fun search()
}

// Case 2: Classes inheriting from base class
class SpotifyRepositoryImpl : BaseMusicPlayerRepository() {
    // Only needs to implement search() because play() is already 
    // implemented in the base class
    override fun search() {
        // Spotify-specific search using their API
    }
}

class LocalFilesRepositoryImpl : BaseMusicPlayerRepository() {
    // Only needs to implement search()
    override fun search() {
        // Local filesystem search
    }
    
    // Can optionally override play() if needed
    override fun play() {
        // Custom implementation for local files
    }
}
Which of the approaches is considered more correct/ elegant?
.. or perhaps dependency injection should be opted for in every case?
Copy code
// Instead of inheritance:
abstract class BaseFileManager { ... }
class LocalFileManager : BaseFileManager()

// Prefer composition:
interface FileManager { ... }
class LocalFileManager(
    private val commonFileLogic: CommonFileLogic
) : FileManager
n
it is a good peactice of course. Don't commit the mistake to force classes to implement interfaces that they shouldn't
Prefer compositions and dont abuse of interfaces. One very common mistake is to create interfaces and impls that are not startegy just because we have tests and we think that we are isolating implementations. Interafces must have a real reason to exist