Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]: Reliant/Swift: Context substitution #18

Open
wants to merge 3 commits into
base: feature/reliant-in-swift
Choose a base branch
from

Conversation

aceontech
Copy link
Contributor

⚠️ Work-in-progress, do not merge ⚠️

Exploring a way to register context substitutions so they can be swapped out for testing or other purposes.

Current implementation

I added a map to the context cache which will be accessible through relyOnSubstitute(T)(T). This global function simply creates an entry in the map, which relyOn() will then use to determine if it needs to create a substitute context or a normal one, when requested.

Remarks

I have only gotten this to work half-way. The substitute type is registered and found correctly, but when its createContext() function is invoked, the original, non-substituted version is called because createContext() is static with no way to override it, because static also means final in Swift.

Because of how I set up the relyOnSubstitute's arguments (both of the same type T:ReliantContext), the second argument needs to resolve to the same type as the first. That is, the second argument needs to be covariant with the first. This is currently achieved by subclassing the original context, with currently no way to modify createContext()'s implementation due to the reason stated above.

Subclassing doesn't feel right, so I'm currently exploring ways to change relyOnSubstitutes signature to something like:

public func relyOnSubstitute<T:ReliantContext, S:ReliantContext>(type:T.Type)(_ otherType:S.Type)

This causes serious type resolution problems of course, so I'm still trying to figure something out.

@aceontech aceontech added this to the 3.0 milestone Mar 4, 2016
@aceontech aceontech self-assigned this Mar 4, 2016
class SubstituteContext : SimpleReferenceContext {
override init() {
super.init()
waver = SubWaver()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted in the summary, having to subclass feels icky and rules out the use of struct-based contexts. It also requires class members to be mutable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we work through protocols and delegation instead?
Eg: protocol Waver, structs RealWaver and SubWaver, SubWaver initialises RealWaver and delegates to it when needed, overriding it's behaviour when wanted? It would mean people need some knowledge on how to architect this in, but it's better than having the above mentioned restrictions...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the current method is pretty much a no-go. I think there are still some alternatives to explore though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants