Created
April 10, 2019 13:34
-
-
Save JorgeCastilloPrz/eaaedfcc5a02bb2a38c2120a903f9ca9 to your computer and use it in GitHub Desktop.
Keep87Sample project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.data.instances | |
import com.data.Repository | |
import com.domain.Group | |
import com.domain.User | |
extension class GroupRepository(with val userRepository: Repository<User>) : Repository<Group> { | |
override fun loadAll(): List<Group> { | |
return listOf(Group(userRepository.loadAll())) | |
} | |
override fun loadById(id: Int): Group? { | |
return Group(userRepository.loadAll()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.consumer | |
import com.data.Repository | |
import com.domain.Group | |
import com.domain.User | |
import com.validation.Validator | |
fun <A> validate(a: A, with validator: Validator<A>): Boolean = a.isValid() | |
fun <A> retrieveIfValid(id: Int, with repository: Repository<A>, with validator: Validator<A>): A? { | |
val x = loadById(id) | |
if (x == null) return null | |
return if (validate(x)) x else null | |
} | |
fun program(): String { | |
val user = retrieveIfValid<User>(25) | |
if (user != User(25, "Bob")) { | |
return "fail 1" | |
} | |
val group = retrieveIfValid<Group>(1) | |
return if (group == Group(listOf(User(25, "Bob")))) { | |
"OK" | |
} else { | |
"fail 2" | |
} | |
} | |
fun main(args: Array<String>) { | |
/** | |
* Resolution order for extensions is (in this strict order): | |
* | |
* - 1) Scope of the caller function. | |
* - 2) Companion object for the type (User). | |
* - 3) Companion object for the contract interface we're looking for (Repository, Validator). | |
* - 4) Subpackages of the type to resolve (User). | |
* - 5) Subpackages of the contract interface (Repository, Validator). | |
* | |
* This program has the following requirements to run (constraints): | |
* - An extension for Repository<User>, provided in com.data.instances.UserRepository (subpackages of the contract interface, Repository (5)). | |
* - An extension for Repository<Group>, provided in com.data.instances.GroupRepository (subpackages of the contract interface, Repository (5)). | |
* - An extension for Validator<User>, provided in com.domain.User Companion (companion object for the type (2)). | |
* - An extension for Validator<Group>, provided in com.validation.Validator Companion (companion object for the contract interface (3)). | |
* | |
* All of them are fulfilled, so the program completes successfully. | |
*/ | |
println(program()) // successful! | |
/** | |
* Now, try to remove any of the provided extensions from any of the required places, you'll see compile time detailed errors about extensions | |
* not able to resolve. You'll get errors inlined (underline + IDE inspections) and when you hit compile button / run any compile commands. | |
*/ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.data | |
interface Repository<A> { | |
fun loadAll(): List<A> | |
fun loadById(id: Int): A? | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.domain | |
import com.validation.Validator | |
data class User(val id: Int, val name: String) { | |
companion object { | |
extension class UserValidator(): Validator<User> { | |
override fun User.isValid(): Boolean { | |
return id > 0 && name.length > 0 | |
} | |
} | |
} | |
} | |
data class Group(val users: List<User>) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.data.instances | |
import com.data.Repository | |
import com.domain.User | |
extension object UserRepository: Repository<User> { | |
override fun loadAll(): List<User> { | |
return listOf(User(25, "Bob")) | |
} | |
override fun loadById(id: Int): User? { | |
return if (id == 25) { | |
User(25, "Bob") | |
} else { | |
null | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.validation | |
import com.domain.Group | |
import com.domain.User | |
interface Validator<A> { | |
fun A.isValid(): Boolean | |
companion object { | |
extension class GroupValidator<A>(with val userValidator: Validator<User>) : Validator<Group> { | |
override fun Group.isValid(): Boolean { | |
for (x in users) { | |
if (!x.isValid()) return false | |
} | |
return true | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment