In this chapter, we learned how structural design patterns help us to create more flexible code that can adapt to changes with ease, sometimes even at runtime. We've covered operator overloading in Kotlin and its limitations. You should know how to create a shortcut to a type name with typealias and how to define efficient constants with const.
We've covered how delegating to another class works in Kotlin, by implementing the same interface and using the by keyword.
In addition, we covered functions that can receive an arbitrary number of arguments with vararg and lazy initialization with lazy.
In the next chapter, we'll discuss the third family of classical design patterns: behavioral patterns.