简体   繁体   中英

inject concrete type at runtime in swift

Is it at all possible to have a concrete type injected at runtime. For example, let's say you have two frameworks that have the same methods with different implementations:

FrameworkA
func name() -> String {
  return "A"
}

FrameworkB
func name() -> String {
  return "B"
}

So you create a protocol in FrameworkC

FrameworkC
protocol Namable {
  func name() -> String
}

class SomeOtherClass {
    // uses Namable
}

Then in an actual app that uses FrameworkC, can you embed or link just FrameworkA and then FrameworkA's implementations would be used? And similarly some other consumer of FrameworkC could use FrameworkB's implementations?

I've done something similar, but not with frameworks per-se. Imagine you have an app, and you want another app that includes all the code of the first app plus some "tweaks" to the functionality of that code. And you want to minimize what has to change in the first (base) app's codebase. (ie I didn't want to subclass as that will quickly wind up refactoring the base code in many undesireable ways.)

I've actually successfully written & shipped several iOS apps "atop" another iOS app (where each other app is just a set of tweak code plus the underlying app's code. The base app's code merely had to call some extra methods that do nothing in the base app - methods that conformed to a specific protocol. The base app had no significant change, yet its codebase was tweaked and extended in major ways by another app (actually several) that also compiled in that codebase.

By using protocol extensions and the where clause to target a specific concrete class that implements the protocol, you can achieve targeted "tweaks" of a base set of code (say, of a first app) simply by adding extra code files to the (second) app. It can be a very powerful way to extend the base functionality of a codebase without re-architecting or rearranging the base code at all.

So try having Framework A and B both extend your Namable protocol with "where" clause to target a concrete class of Framework C. And Framework C should probably have the same extension too, just with empty no-op methods. So Framework A or B can basically provide a plugin-able implementation for the empty protocol'd method of Framework C, in a way where Framework C knows nothing about A and B. You can basically target a specific method of a specific class in this way, replacing its contents merely by the presense of other code being linked in (the extension protocol with where clause).

It's one of the most miraculous things about Swift, IMHO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM