140 likes | 246 Views
This article explores the differences between dynamic and static typing in object-oriented programming (OOP). Dynamic typing allows for flexibility at runtime, enabling operations based on the data type without needing explicit declarations. This approach can lead to runtime errors if not handled properly. Conversely, static typing enforces type checks at compile-time, preventing type-related errors before execution, but requires more extensive code. The implications of both typing systems on program design, error handling, and flexibility in OOP languages are discussed comprehensively.
E N D
Object Oriented Programming 236703 Spring 2007 Types
Values 5 Color.RED "abc" new String[20] new Scanner("c:/temp/in.txt") new Properties()
Supported Operations int x = 5; Color.RED == null "abc".equalsIgnoreCase("ABC") (new String[20])[0] new Scanner("c:/temp/in.txt").next() new Properites(0).getProperty("a")
Unsupported Operations int x = 5.9; Color.RED.equals(5,5) "abc".remove(0) (new String[20])[0][0] = "xyz"; new Scanner("c:/temp/in.txt") = null Integer.parseInt(Properites(0))
Dynamic Typing • The dynamic typing approach: • Compile-time: Allow all operations • Run-time: Before carrying out an operation, check that it is supported by the value • Requirement: • A run-time data structure that determines the “support” question • Consequences: • Assignments to variables never fail • No need to define types (of variables, return types, etc.) • Flexibility • Run-time errors if we are not careful
Static Typing • The static typing approach: • Compile-time: Check that operations are correct • Run-time: Just carry out the operation • The idea: The compiler “simulates” the evaluation of expressions • Compile-time computation of the type of the expression • Corresponds to the run-time computation of the result of the expression • If a type cannot be computed => Compilation error • The computed type of subexpressions is used in computing the type of bigger expressions
Static Typing (cont.) • Requirements • Variables have types • Methods have return types • Assignments are checked by the compiler • Message sends are checked by the compiler • Consequences • More type errors are detected at compile-time • Programmer must type more text • Not as flexible: “You can't always do what you want” • Invocation of an action is faster • But this factor becomes less and less important...
Supported? Yes/No?DT = Dynamic Typing; ST = Static Typing interface List { void add(Object o); } class ArrayList implements List { void add(Object o) { ... } } class LinkedList implements List { void addFirst(Object o) { ... } void add(Object o) { ... } } LinkedList w = new LinkedList(); w.addFirst("1"); // DT ST List x = new LinkedList(); x.addFirst("1"); // DT ST List y = new ArrayList(); y.addFirst("1"); // DT ST LinkedList z = new ArrayList(); // ST z.addFirst("1"); // DT
What is a Type? • Theoretically a type is defined as a set of values • A more practical definition: A function that maps a value to either “yes”/”no” • The type is the set of all sources that are mapped to “yes” • The compiler usually represents types as a directed graph • Two types of nodes: Messages, Types • Edges are labeled (ordinal numbers) • A type node has outgoing edges to all messages it can receive • A message node has outgoing edges to its return type, types of its parameters
Type Checking: Statically Typed Language • Occurs when the compiler encounters an assignment • (Parameter passing is actually a sequence of assignments) void f(F f) { R r = f; // <- Type checking ...} • The idea: Compare the set of messages of F, R • In Java: • A subtype shares messages with its supertypes • The sets are compared for inclusion (not equality)
Subtyping Schemes • Nominal subtyping: A type Y shares messages with X if Y declares X as a super type • A fixed set of super types • Structural conformance: A type Y shares messages with X if the messages have the same signature • One node for all messages of with the same signature • Regardless of where the messages are defined • An unlimited set of super types • This is actually a recursive definition
Nominal vs. StructuralN = Nominal; S = Structural public interface R1 { public void a(); } public interface R2 { public void a(); } public interface F extends R1 { public void b(); } void g(F f) { R1 r1 = f; // N: S: R2 r2 = f; // N: S: ... }
Typing Holes • Recall: A type system should prevent us from applying an operation to a value that does not support it • Is it really so? public class A { void f() { ... } } .. void g(A a) { a.f(); } • What values (of the variable a) will not support the operation a.f() ?
Typing Strength • Strong typing: • An unbreakable association between a value and its type • Weak typing: • One can change the value-type association • Modern languages: Strong typing • With either static or dynamic type checking