7

In Swift, an extension is a way to define members for classes after the fact. Or, you could say, it is (coming from a total newb) fancy way of composing a function:

extension Double {
    var mm: Double { return self * 1_000.0 }
    func mm1() -> Double { return self * 1_000.0 }
}

func mm(a: Double) -> Double {
    return a * 1_000.0
}

print("One meter is \(1.mm) milimeters")
print("One meter is \(1.mm1()) milimeters")
print("One meter is \(mm(1)) milimeters")

I have never seen something like this. Is there anything like this in any other languages?

hgiesel
  • 5,430
  • 2
  • 29
  • 56
  • C# has something similar: https://msdn.microsoft.com/en-us/library/bb383977(v=vs.110).aspx – hnh May 08 '16 at 20:57
  • You can augment JavaScript classes using their prototype (though it's strongly discouraged for built-ins such as arrays). Or more directly, I believe that with the way Go is structured, it's impossible to have methods defined any other way. A similar principle would apply in C if you make some functions to operate on structs (which is object-orientation just without the fancy syntax), and that's a pattern you could use in almost any language if you were so inclined. – Dave May 08 '16 at 21:05
  • Oh, and of course Smalltalk and ObjC can do that via categories. Though those work differently than Swift extensions (they monkey-patch ;-). https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html – hnh May 08 '16 at 21:26
  • @Dave I know of JS, but I don't think it counts, because it doesn't really have classes, but rather prototypes. C doesn't have anything which encapsulates functionality like a class. – hgiesel May 08 '16 at 21:52
  • *ahem* http://stackoverflow.com/q/351733/1180785 (see especially second answer). Just because it doesn't have a nice syntax for it, doesn't mean you can't do it. – Dave May 09 '16 at 07:09

2 Answers2

5

Yes other languages have features like extensions. As @hnh points out C# has a very similar feature

It also makes it clear this feature is not "monkey patching"

Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type

To put it another way extensions are more like a syntactic sugar. Given the example in the question, Double, you could just make a function that takes a Double (as shown in the question)

func mm(a: Double) -> Double {
    return a * 1_000.0
}

And then you could call it directly

var foo = 12.34;
print("One meter is \(mm(foo)) millimeters")

What effectively happens with extensions in both C# and Swift is the extension tells the compiler to translate behind the scenes

someDouble.mm()

into

mm(someDouble)

or in our case more like

__extension_for_type_Double_mm(someDouble as self)

So, nothing is patched.

This also means you can have more than one mm extension from different modules and choose which one to use per file by only importing that module in that file where as some other file can import another module with another extension for the same type with the same name. This is not possible with monkey patching because the object or its class/prototype gets patched (something actually changes). Here, nothing changes, it's just syntactic sugar for calling a stand alone function.

This means features like monkey-patching in Ruby and JavaScript are not the same as extensions.

gman
  • 100,619
  • 31
  • 269
  • 393
  • In Swift, an extension can make a type conform to a protocol (which is similar to a C# interface). This is called “retroactive conformance”. Does C# have anything like that? (I know the original question didn't ask about this.) – rob mayoff Feb 23 '19 at 06:40
  • The linked C# docs show an example of conforming to an interface using C# extensions – gman Feb 23 '19 at 07:05
  • Which example does that? The only interface I see in the linked page is `IMyInterface`, and all of the classes that conform to it (`A`, `B`, and `C`) do so directly in their declarations. – rob mayoff Feb 23 '19 at 09:04
  • 1
    You should probably ask a C# tagged question showing what you were able to achieve in swift and asking how to do the same in C#. Comments are not a good place to discuss this. – gman Feb 23 '19 at 09:26
0

This is called monkey patch. There are a few of other languages supporting it such as Ruby

SwiftMango
  • 15,092
  • 13
  • 71
  • 136
  • 6
    I highly doubt anyone would consider Swift extensions as monkey patching. They are isolated extensions which do not even come into effect unless you import the module defining them into the compilation unit. That is quite different to the monkey-patching people do in JavaScript, ObjC and Ruby. – hnh May 08 '16 at 21:02
  • 2
    @hnh I don't think being isolated or not would change the definition. It looks like a monkey, it works like a monkey, then it is a monkey – SwiftMango May 08 '16 at 21:16
  • 2
    It may be a monkey, but the key is that it's not a patch ;-) I'd say the key aspect of monkey patching is that you modify the dynamic runtime of the language to replace or add methods. Eg you redefine the binding of a key of a JS object to a new function, or you do a similar thing via method swizzling in ObjC. Swift extensions are nothing like that. Nothing gets patched, all is cleanly separated, no monkey'ing around. – hnh May 08 '16 at 21:21
  • 1
    Looking into the details @hnh is correct. It's not a monkey patch. Rather it's syntactic sugar for type specific functions. In other words the example above is effectively making a function `__Double__mm` and then when it sees `someDouble.mm()` it translates that into something like `__Double__mm(someDouble as self)`. Nothing was patched. There are no monkeys. – gman Feb 23 '19 at 05:11
  • I am familiar with monkey patching in Ruby/JavaScript and was trying to find out whether it is same with extensions in Swift. Turns out it is different (more like a macro in lisp!) Thanks! – lks128 May 06 '20 at 20:41