Skip to content

Instantly share code, notes, and snippets.

@n8gray
Created June 7, 2014 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save n8gray/15224c6e77e080c072af to your computer and use it in GitHub Desktop.
Save n8gray/15224c6e77e080c072af to your computer and use it in GitHub Desktop.
Testing Swift array variance
//
// ArrayTest.swift
// SwiftTest
//
// Swift array subtyping semantics test
//
// Created by Nathan Gray on 6/7/14.
// Copyright (c) 2014 Mellmo. All rights reserved.
//
import Foundation
// A base class
class Base {}
// A couple of subclasses
class Sub1 : Base {
var name : String = "Nobody"
init(name:String) { self.name = name }
}
class Sub2 : Base {
var age : Int = 1
}
// A silly function to test upcasting
func tupleDuple(x : Base) -> (Base, Base) {
return (x, x)
}
// A simple function that takes a read-only array
func sub(arr : Base[], i : Int) -> Base {
return arr[i];
}
// A simple function that mutates an array
func append(inout arr : Base[], x : Base) {
arr += x
}
// A polymorphic function that mutates an array
func polyAppend<T>(inout arr : T[], x : T) {
arr += x
}
// // // // // // // // // // // // // // // // // // // // // // // //
func arrayTestMain() {
// This works, demonstrating that implicit upcasts of function arguments are allowed
let tup = tupleDuple(Sub1(name:"Twin"))
// Make an array of subclass objects
var arr = Sub1[]()
arr += Sub1(name:"Alice")
arr += Sub1(name:"Joe")
// This should work, simply substitute Sub1 for T
polyAppend(&arr, Sub1(name:"Bob"))
// This should also work, since the array is passed read-only
// It's actually "copied", but semantically it's read-only -- passing it in
// will not cause it to be mutated.
var x = sub(arr, 0)
// These are unsafe and should both fail...
append(&arr as Base[], Sub2() as Base)
polyAppend(&arr as Base[], Sub2() as Base)
// Hooray! Both of them fail to compile, even with explicit casts!
// Java famously got this wrong and allows passing a
// mutable array of Sub1 to a function that expects an array of Base.
// This forces them to do runtime safety checks on *every* array subscript.
for s1 in arr {
println("Hello \(s1.name)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment