'Injecting a single dependency to a view model

I want the LoginViewModel to have a single dependency of LoginViewModelService. 
LoginViewModelService in itself cannot have an implementation. Its methods will be implemented by both the LoginController and AccountController.

The challenge I’m having right now is, when I instantiate the LoginViewModel which has the single dependency of LoginViewModelService, there is no way I can inject Login Controller and the Account Controller as its implementation class even though they implement the methods of the LoginViewModelService.

To get a better idea I have attached the code from my playground.

What I hope I can do is, there is some way to accomplish the single dependency structure but if thats impossible I would like your recommendation on how I should approach this. Basically my objective is that the service being used by the Login View Model should not have access to method that it does not need, for example Logout() from the Login Controller class or the delete() from the Account controller class.

class AccountController {
    func create() {print("Create")}
    func get() {print("get")}
    func update() {print("update")}
    func delete() {print("delete")}
}
// protocol LoginController {   
// ...
// }

class LoginController {
    func apple() {print("apple")}
    func google() {print("google")}
    func phone() {print("phone")}
    func logout() {print("logout")}
}

protocol LoginViewModelService {
    func apple()
    func google()
    func phone()
    func get()
}
extension LoginViewModelService {
    func apple(){}
    func google(){}
    func phone(){}
    func get(){}
}

class ViewModel {
    init(serivice: LoginViewModelService) {}
}


let accountController = AccountController()
let loginController = LoginController()

extension AccountController: LoginViewModelService {}
extension LoginController: LoginViewModelService {}


// -------------------------This is what I hope I can do-------------
let vm = ViewModel(serivice: accountController & loginController)
// -------------------------------------------------------------------


Solution 1:[1]

After playing with it I came up with this solution.

protocol CurrentProfileProvider {
    func getMyProfile()
}
protocol ProfileCreator {
    func create()
}
protocol ProfileUpdater {
    func update(onlyLocally: Bool)
}
protocol ProfileDeleter {
    func delete()
}

protocol ConversationCreator {
    func create()
}

protocol ListenersProvider {
    func listenersList() -> [String]
}

protocol AccountController:CurrentProfileProvider,ProfileCreator,ProfileUpdater,ProfileDeleter {}

class AccountControllerImpl:AccountController {
    func update(onlyLocally: Bool) {}
    func create() {print("Create")}
    func getMyProfile() {print("Get my profile")}
    func delete() {print("delete")}
}

protocol LoginProvider {
    func apple()
    func google()
    func phone()
}
protocol Logout {
    func logout()
}
protocol AuthenticationController: LoginProvider, Logout {}

class AuthenticationControllerImpl:AuthenticationController {
    func apple() {print("apple")}
    func google() {print("google")}
    func phone() {print("phone")}
    func logout() {print("logout")}
}
class ViewModel {
    let service: Service
    init(service: Service) {
        self.service = service
    }
}
extension ViewModel {
    class Service {
        let ac: CurrentProfileProvider
        let lc: LoginProvider
        
        init(ac: CurrentProfileProvider, lc: LoginProvider) {
            self.ac = ac
            self.lc = lc
        }
    }
}
let ac = AccountControllerImpl()
let lc = AuthenticationControllerImpl()

let service = ViewModel.Service(ac:ac ,lc: lc)
let vm = ViewModel(service: service)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Minon Weerasinghe