In Xcode 7, Apple has introduced 'Lightweight Generics' to Objective-C. In Objective-C, they will generate compiler warnings if there is a type mismatch.
NSArray<NSString*>* arr = @[@"str"];
NSString* string = [arr objectAtIndex:0];
NSNumber* number = [arr objectAtIndex:0]; // Warning: Incompatible pointer types initializing 'NSNumber *' with an expression of type 'NSString *'
And in Swift code, they will produce a compiler error:
var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
Lightweight Generics are intended to be used with NSArray, NSDictionary and NSSet, but you can also add them to your own classes:
@interface GenericsTest<__covariant T> : NSObject
-(void)genericMethod:(T)object;
@end
@implementation GenericsTest
-(void)genericMethod:(id)object {}
@end
Objective-C will behave like it did before with compiler warnings.
GenericsTest<NSString*>* test = [GenericsTest new];
[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
but Swift will ignore the Generic information completely. (No longer true in Swift 3+.)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
Aside from than these Foundation collection classes, Objective-C lightweight generics are ignored by Swift. Any other types using lightweight generics are imported into Swift as if they were unparameterized.
Interacting with Objective-C APIs
What is the difference between a strongly typed language and a statically typed language?
A statically typed language has a type system that is checked at compile time by the implementation (a compiler or interpreter). The type check rejects some programs, and programs that pass the check usually come with some guarantees; for example, the compiler guarantees not to use integer arithmetic instructions on floating-point numbers.
There is no real agreement on what "strongly typed" means, although the most widely used definition in the professional literature is that in a "strongly typed" language, it is not possible for the programmer to work around the restrictions imposed by the type system. This term is almost always used to describe statically typed languages.
Static vs dynamic
The opposite of statically typed is "dynamically typed", which means that
- Values used at run time are classified into types.
- There are restrictions on how such values can be used.
- When those restrictions are violated, the violation is reported as a (dynamic) type error.
For example, Lua, a dynamically typed language, has a string type, a number type, and a Boolean type, among others. In Lua every value belongs to exactly one type, but this is not a requirement for all dynamically typed languages. In Lua, it is permissible to concatenate two strings, but it is not permissible to concatenate a string and a Boolean.
Strong vs weak
The opposite of "strongly typed" is "weakly typed", which means you can work around the type system. C is notoriously weakly typed because any pointer type is convertible to any other pointer type simply by casting. Pascal was intended to be strongly typed, but an oversight in the design (untagged variant records) introduced a loophole into the type system, so technically it is weakly typed.
Examples of truly strongly typed languages include CLU, Standard ML, and Haskell. Standard ML has in fact undergone several revisions to remove loopholes in the type system that were discovered after the language was widely deployed.
What's really going on here?
Overall, it turns out to be not that useful to talk about "strong" and "weak". Whether a type system has a loophole is less important than the exact number and nature of the loopholes, how likely they are to come up in practice, and what are the consequences of exploiting a loophole. In practice, it's best to avoid the terms "strong" and "weak" altogether, because
Amateurs often conflate them with "static" and "dynamic".
Apparently "weak typing" is used by some persons to talk about the relative prevalance or absence of implicit conversions.
Professionals can't agree on exactly what the terms mean.
Overall you are unlikely to inform or enlighten your audience.
The sad truth is that when it comes to type systems, "strong" and "weak" don't have a universally agreed on technical meaning. If you want to discuss the relative strength of type systems, it is better to discuss exactly what guarantees are and are not provided.
For example, a good question to ask is this: "is every value of a given type (or class) guaranteed to have been created by calling one of that type's constructors?" In C the answer is no. In CLU, F#, and Haskell it is yes. For C++ I am not sure—I would like to know.
By contrast, static typing means that programs are checked before being executed, and a program might be rejected before it starts. Dynamic typing means that the types of values are checked during execution, and a poorly typed operation might cause the program to halt or otherwise signal an error at run time. A primary reason for static typing is to rule out programs that might have such "dynamic type errors".
Does one imply the other?
On a pedantic level, no, because the word "strong" doesn't really mean anything. But in practice, people almost always do one of two things:
They (incorrectly) use "strong" and "weak" to mean "static" and "dynamic", in which case they (incorrectly) are using "strongly typed" and "statically typed" interchangeably.
They use "strong" and "weak" to compare properties of static type systems. It is very rare to hear someone talk about a "strong" or "weak" dynamic type system. Except for FORTH, which doesn't really have any sort of a type system, I can't think of a dynamically typed language where the type system can be subverted. Sort of by definition, those checks are bulit into the execution engine, and every operation gets checked for sanity before being executed.
Either way, if a person calls a language "strongly typed", that person is very likely to be talking about a statically typed language.
Best Answer
"Strongly typed" and "weakly typed" are terms that have no widely agreed-upon technical meaning. Terms that do have a well-defined meaning are
Dynamically typed means that types are attached to values at run time, and an attempt to mix values of different types may cause a "run-time type error". For example, if in Scheme you attempt to add one to true by writing
(+ 1 #t)
this will cause an error. You encounter the error only if you attempt to execute the offending code.Statically typed means that types are checked at compile time, and a program that does not have a static type is rejected by the compiler. For example, if in ML you attempt to add one to true by writing
1 + true
, the program will be rejected with a (probably cryptic) error message. You always get the error even if the code might never be executed.Different people prefer different systems according in part to how much they value flexibility and how much they worry about run-time errors.
Sometimes "strongly typed" is used loosely to mean "statically typed", and "weakly typed" is used incorrectly to mean "dynamically typed". A better use for the term "strongly typed" is that "you cannot work around or subvert the type system", whereas "weakly typed" means "there are loopholes in the type system". Perversely, most languages with static type systems have loopholes, while many languages with dynamic type systems have no loopholes.
None of these terms are connected in any way with the number of implicit conversions available in a language.
If you want to talk precisely about programming languages, it is best to avoid the terms "strongly typed" and "weakly typed". I would say that C is a language that is statically typed but that has a lot of loopholes. One loophole is that you can freely cast any pointer type to any other pointer type. You can also create a loophole between any two types of your choice by declaring a C union that has two members, one for each of the types in question.
I have written more about static and dynamic typing at why-interpreted-langs-are-mostly-ducktyped-while-compiled-have-strong-typing.