Should extension be able to change behaviour of + in Array?

This is my first posting here so please forgive me if I have put this in the wrong place or not well expressed my question.

I have recently noticed that I can do the bellow and extend Array to change the behaviour of + (I have included a complete example below that works in playgrounds).

It seems to me that this breaks the open-closed principle.

Please can you let me know if this should require an explicit override?

Also is there a way to warn users that functionality like this has changed if it has happened?

Many thanks in advanced for any help.

extension Array where Element == Double {
static func + (left: Array, right: Array) -> Array {
return zip(left,right).map(+)
}
}

let testDouble = [1.0,2.0]+[3.0,4.0]
// [4.0,6.0]
let testInt = [1,2]+[3,4]
// [1,2,3,4]

1 Like

Yes, you can shadow pretty much any standard library method locally. You can even change the relative precedence of the operator. This is all deliberately permitted in Swift.

4 Likes

Thank you - it is good to know it is intended behaviour.

I am still worried about this as the effect is not just limited to module scope.

I tried putting this code in a module and then importing the module. I saw the extended behaviour outside the library in main.

Do you have any advice on limiting the effect of such an extension to within module please?

"Don't do it".

The shadowing behavior is there mostly so that existing functionality in non-stdlib modules isn't broken when the standard library adds a new feature. Deliberately shadowing an existing standard library feature is just a bad idea.

9 Likes

Thank you & I dont intend to.

It is good to know the rational for it being possible. When I see something like this I like to try to understand it so I am aware of possible causes of unusual errors when e.g. using third party code.

1 Like

I think the real problem here is that operator declarations don’t respect module boundaries.

That’s a known issue, though I don’t have a bug reference handy.

3 Likes

Thank you - I will look for the bug report and if I find it update this post.

I have just rechecked this and now it appears that the change in behaviour is limited to module level unless the extension is marked public.

So without the public modifier all seems good now (by this I mean that one can, if one wished, override +, sort() etc within a module but not change their behaviour outside of that module).

But if I make the extension in the module public then behaviour is changed in main. Doesn't this mean someone can change e.g. sort() and maybe keep it behaving the same in way in terms of observed behaviour but also make it do something malicious? If this was in a library where source code was not present could it be a security risk?

even outside of overriding "+", etc - libraries have access to app's memory and can do pretty much anything with it they want.

third party code is a security risk (remember recent SolarWinds case). binary code especially, but also so when sources are available, unless you carefully audit the sources and keep doing this with every new version of the library you use. the unfortunate scenario for you is when you heavily depend upon a third party library and then forced to use a newer version of it (e.g. to support a new OS version) and that newer version introduces something that is against your (company) rules, be it a binary component or a licence change or a dependency upon another library that you can't use for some reason.

3 Likes

That is a good point. I personally manage to avoid third party libraries most of the time.

In my teaching I do go over some risks of using third part libraries to my students (which is not as usual as you might hope in the physical sciences). I may just quote you if you dont mind?

sure thing, but only if you like my post :wink:

1 Like