Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.87 KB | None | 0 0
  1. import kotlin.reflect.KClass
  2. import kotlinx.coroutines.*
  3.  
  4. fun main() {
  5. println("Welcome to Thingville, population 1")
  6. val factory = ThingFactory(Thing1::class)
  7. factory?.run() // "Run Fast!"
  8. factory?.play() // "Run Hard!"
  9. val factory2 = ThingFactory(Thing2::class) // Run Time Error: Already created as type: class Thing1
  10. val factory3 = ThingFactory(NoThing::class) // Compile Time Error: None of the following functions can be called with the arguments supplied: public constructor ThingFactory(clazz: ThingFactory.ThingType) defined in ThingFactory public inline fun <reified T : SomeThing> ThingFactory(clazz: KClass<???>): ThingFactory?
  11. // Thread safe check
  12. runBlocking {
  13. val deferred = (1..20).map { n ->
  14. GlobalScope.async {
  15. val r = (1..10).random()
  16. println("In ${n}")
  17. try {
  18. when {
  19. r % 2 == 0 -> {
  20. println("Create ${n} Thing1")
  21. ThingFactory(Thing1::class)
  22. }
  23. else -> {
  24. println("Create ${n} Thing2")
  25. ThingFactory(Thing2::class)
  26. }
  27. }
  28. } catch(e: RuntimeException) {
  29. println("Error ${n} : ${e.message}")
  30. }
  31. println("Out ${n}")
  32. }
  33. }
  34. deferred.awaitAll()
  35. }
  36. }
  37.  
  38. sealed class SomeThing {
  39. abstract fun run()
  40. abstract fun play()
  41. }
  42.  
  43. class Thing1: SomeThing() {
  44. override fun run() = println("Run Fast!")
  45. override fun play() = println("Play Hard!")
  46. }
  47. class Thing2: SomeThing() {
  48. override fun run() = println("Run Silly!")
  49. override fun play() = println("Play Soft!")
  50. }
  51.  
  52. class NoThing {}
  53.  
  54. interface ClassBackedEnum {
  55. fun toClass(): Any
  56. }
  57.  
  58. inline fun <reified T: SomeThing> ThingFactory(clazz: KClass<T>): ThingFactory? =
  59. when(clazz) {
  60. Thing1::class -> ThingFactory(ThingFactory.ThingType.Thing1Type)
  61. Thing2::class -> ThingFactory(ThingFactory.ThingType.Thing2Type)
  62. else -> throw RuntimeException("Unknown type: $clazz")
  63. }
  64.  
  65. class ThingFactory private constructor() {
  66. enum class ThingType(): ClassBackedEnum {
  67. Thing1Type {
  68. override fun toClass() = Thing1::class
  69. },
  70. Thing2Type {
  71. override fun toClass() = Thing2::class
  72. }
  73. }
  74.  
  75. constructor (clazz: ThingType): this() {
  76. if (myThing == null) {
  77. when(clazz.toClass()) {
  78. Thing1::class -> myThing = Thing1()
  79. Thing2::class -> myThing = Thing2()
  80. }
  81. } else {
  82. if (myThing?.javaClass?.kotlin != clazz.toClass()) {
  83. throw RuntimeException("Already created as type:${myThing?.javaClass?.kotlin}")
  84. }
  85. }
  86. }
  87.  
  88. fun run() {
  89. myThing?.run()?: throw RuntimeException("Singleton not instantiated")
  90. }
  91.  
  92. fun play() {
  93. myThing?.play()?: throw RuntimeException("Singleton not instantiated")
  94. }
  95.  
  96. companion object {
  97. @Volatile var myThing: SomeThing? = null
  98. @Synchronized set(value: SomeThing?) {
  99. val i = myThing
  100. if (i != null) {
  101. field = i
  102. } else {
  103. field = value
  104. }
  105. }
  106. }
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement