3 ms·
> What an object is, which is roughly equivalent to its observed behavior, should never depend on how it is declared. This is actually a statement that strong
by torpidor 8y ago
> What an object is, which is roughly equivalent to its observed behavior, should never depend on how it is declared.
This is actually a statement that strong typing should not exist. A "declaration" (really a type declaration) indicates the type, and if observed behavior cannot depend on the types there is not much point to types. Or stated positively: in a strongly typed language, the types are part of 'what an object is'.
Or, stated by example:
let a: Int = 3
let b: Float = 3
print(a/2) //prints 1
print(b/2) //prints 1.5
Both a and b are "the same" value, insofar as they are `==` and they model the same underlying mathematical concept. But behavior varies because they differ in type.
OP's snippet actually works quite a lot differently than the way you may expect; LazyGreeter.greet() and Greeter.greet() are two completely independent functions that share the same name. Name resolution is a complex topic in any language, but in Swift if you wanted to override another function you would say `override`, in which case the compiler will complain there is nothing you can override in `BaseGreeter` at which point you will understand the whole mistake.
There is actually no way to "pick" LazyGreeter's implementation of the unrelated function (as perhaps you expect). The only function we can call on a Greeter is Greeter.greet (or its overloads, and there are none). So if Greeter.greet did not exist, we would not get LazyGreeter.greet() but rather a type error.
I do think a case can be made that we need a similar `implements` keyword like `override` to check that we are implementing a protocol requirement.
- Black-Plaid 8y agoInterestingly, in Swift, you Cannot compare `a == b` as the compiler tells you the two types are incompatible.
- wz1000 8y agoHaskell has no problem with this(though its default Num hierarchy is sorely lacking) Prelude> a = 1 Prelude> a/2 0.5 Prelude> :t a/2 a/2 :: Fractional a => a Prelude> b = 1 :: Int Prelude> b/2 <interactive>:6:1: error: • No instance for (Fractional Int) arising from a use of ‘/’ • In the expression: b / 2 In an equation for ‘it’: it = b / 2 Prelude> b `div` 2 0 Prelude> :t div div :: Integral a => a -> a -> a
- wool_gather 8y agoYour example does not have the same structure; `Int` and `Float` are concrete types, not interface types. > strong typing Strong typing is not the same as static typing. `let greeter: Greeter = LazyGreeter()` is a strongly-typed `LazyGreeter`: you cannot use it where a value of another incompatible type is required, nor can you change its runtime type. But its static type is `Greeter`. Swift uses the latter for method resolution, but there's nothing inevitable or inherent about that. `NSArray * array = [NSArray new];` is statically typed as an `NSArray`, but its dynamic (and strong) type is `__NSArray0`, and that's where the value's implementations come from. > they model the same underlying mathematical concept They don't: one models an integral and the other models(/approximates) a real. Which is why, as another commentor already pointed out, they're not `==`.
- mpweiher 8y ago> This is actually a statement that strong typing should not exist. Nope. It is a statement that objects shouldn't be different depending on how you look at them. The example is a class, so a reference type. That means that greeter and greeter1 are just two references to the exact same underlying object. Your example are two distinct value type instances that you happened to initialize from the same literal. So not even close to comparable situations. Speaking of comparable: > Both a and b are "the same" value, insofar as they are `==` Also nope. let a: Int = 3 let b: Float = 3 let r=a==b print(r) Let's compile this: swiftc numbers.swift numbers.swift:4:8: error: binary operator '==' cannot be applied to operands of type 'Int' and 'Float' let r=a==b ~^ ~ numbers.swift:4:8: note: expected an argument list of type '(Int, Int)' let r=a==b ^
- bsaul 8y agoYou may not be familiar with swift but a protocol isn’t necessarily a class. Structs ( so, value type) can also implements a protocol, and so in effect you can not tell a lot about what you’re manipulating, beyond what’s declared at the protocol level.
- mpweiher 8y agoFrom TFA: class BaseGreeter: Greeter {} class LazyGreeter: BaseGreeter {
- torpidor 8y ago> That means that greeter and greeter1 are just two references to the exact same underlying object They are two references that differ in type. It is a feature in Swift (and any strongly-typed language) that references are typed and when types differ, behaviors can differ. I understand you disagree with this design principle but it is an inherent property of strong type systems that have reference semantics. > two distinct value type instances “Nope.” There isn’t any such thing as a “value type instance” since instances are a semantic of reference types. > objects shouldn’t be different depending on how you look at them The “difference” here is only in the types, so this statement is equivalent to “references shouldn’t be different depending on their type.” This statement implies that types should be useless
- arcticbull 8y agoa and b are not the same value, and don't model the same underlying concept. a: Int would be 0x0000000000000003. b: Float would be 0x40400000. While both are specified literally as "3" the compiler de-sugars that into the values above, and further, the type system takes that knowledge into consideration to prevent you from doing things that don't make sense like trying to equate "a" and "b" without explicitly performing a lossy conversion (Binary operator '==' cannot be applied to operands of type 'Float' and 'Int'). I don't believe this to be a name resolution issue, but rather a protocol conformance creates a vtable for the protocol but beyond that dynamic dispatch doesn't exist so it's not possible to resolve the actual method overridden in the subclass. This isn't a statement on typing (other than your example actually making a solid case for strong typing); rather the boundary between static and dynamic dispatch is not well-constructed in the case of protocol conformances.