This material was written by Aasmund Eldhuset; it is owned by Khan Academy and is licensed for use under CC BY-NC-SA 3.0 US. Please note that this is not a part of Khan Academy's official product offering.
Since you can't modify built-in or third-party classes, you can't directly add functions or properties to them. If you can achieve what you want by only using the public members of a class, you can of course just write a function that takes an instance of the class as a parameter - but sometimes, you'd really like to be able to say x.foo(y)
instead of foo(x, y)
, especially if you want to make a chain of such calls or property lookups: x.foo(y).bar().baz
instead of getBaz(bar(foo(x, y)))
.
There is a nice piece of syntactic sugar that lets you do this: extension functions and extension properties. They look like regular member functions/properties, but they are defined outside of any class - yet they reference the class name and can use this
. However, they can only use visible members of the class (typically just the public ones). Behind the scenes, they get compiled down to regular functions that take the target instance as a parameter.
For example, if you work a lot with bytes, you might want to easily get an unsigned byte in the range 0 through 255 instead of the default -128 through 127 (the result will have to be in the form of a Short
/Int
/Long
, though). Byte
is a built-in class that you can't modify, but you can define this extension function:
Now, you can do:
If you'd rather do x.unsigned
, you can define an extension property:
Keep in mind that this is just syntactic sugar - you're not actually modifying the class or its instances. Therefore, you have to import an extension function/property wherever you want to use it (since it isn't carried along with the instances of the class). For the same reason, you can not override extension members - you can reimplement them for subtypes, but the resolution happens at compile-time based on the static type of the expression you're invoking it on. So if you declare an extension function for Vehicle
, and one with the same name and signature for its subclass Car
, and you do the following, it's the extension function on Vehicle
that will be called, even though v
is really a Car
:
There are a lot of built-in extension functions/properties in Kotlin - for example, map()
, filter()
, and the rest of the framework for processing collections in a functional manner is built using extension functions.
← Previous: Generics | Next: Member references and reflection → |
© 2010–2019 JetBrains s.r.o.
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/tutorials/kotlin-for-py/extension-functionsproperties.html