CS 430 Spring 2020

CS 430 Spring 2020

CS 430 Spring 2020 Mike Lam, Professor Abstraction and Object-Oriented Programming Abstraction ● Abstraction is a fundamental concept in CS ● Textbook definition: "a view or representation of an entity that includes only the most significant attributes" ● Mathematical notion: "equivalence classes" ● Practical reality: the first line of defense against software complexity! ● Key: finding the most appropriate level of abstraction Types of abstraction ● Process abstraction – Structured (block) syntax – Subprograms and modules ● Data abstraction – Abstract data types and interfaces ● Polymorphism and generics – Encapsulation and information hiding ● Classes and objects ● Inheritance Abstract data types ● Abstract data type (ADT) – Set of values (carrier set) – List of supported operations ● Common operations: constructor, accessors, iterators, destructors – Not specified: underlying representation ● Exists purely as a mathematical construct ● Examples – List: append(value), get(index), remove(index) – Stack: push(value), pop – Set: add(value), isMember(value), union(otherSet) – Map: store(key, value), lookup(key) – Floating-point: add, sub, mul, div, sqrt Abstract data types ● Concrete data type – Implementation of an ADT on a computer – Specifies value size and format – Often supports only a subset of values from the ADT – Most languages support user-defined concrete data types ● Examples (in Java) – List: ArrayList, LinkedList Set ADT – Set: HashSet, TreeSet – Floating-point: float, double HashSet TreeSet Abstract data types ● Abstract data types can be implemented in some programming languages as data types – Easier w/ encapsulation mechanisms – Even easier w/ information hiding mechanisms – Information hiding implies encapsulation (but not converse) Design issues ● Encapsulation: how is related code and data grouped? – Header files, namespaces, packages, modules, etc. – Structs, unions, classes, interfaces – Modularity and readability; extensibility and maintainability ● Information hiding: should underlying data be exposed? – Levels: public, private, protected – Public fields vs. getters and setters – Convenience/writability vs. safety and extensibility ● Polymorphism: is parameterization possible? – Specifying parameters – Specifying restrictions on the parameters – Power/expressivity vs. readability Encapsulation ● Advantages – Organization – Separate compilation – Avoiding name collisions ● Physical vs. logical encapsulation – Contiguous vs. non-contiguous code ● Naming vs. non-naming encapsulation – Referenced by name vs. not ● Grouping-only vs. information hiding encapsulation – Everything public vs some things non-public Encapsulation Physical Logical Naming Java Class Ruby Class Java Package Ada Package C++ Namespace Ruby Module Non-naming .c, .cpp, or .h file Grouping only .h file Ruby Module C++ Namespace Information hiding .c or .cpp file Ruby Class Java Class Ada Package Java Package Original table courtesy of Dr. Chris Fox Object-oriented programming ● Inheritance – Original motivation: code re-use – Parent/superclass vs. child/derived/subclass – “Pure” vs. hybrid – Overriding methods – Single vs. multiple inheritance (simplicity vs. power) – Static vs. dynamic dispatch (speed vs. power) – Abstract methods and classes – Non-overridable methods: "final" methods in Java Dispatch class DispatchTest1 { void foo(Object o) { System.out.println("foo(Object)"); } void foo(String s) { System.out.println("foo(String)"); } void bar(Object o) { foo(o); } public static void main(String[] args) { (new DispatchTest1()).bar("What gets run?"); } } What will this program print? Dispatch class DispatchTest1 { void foo(Object o) { System.out.println("foo(Object)"); } void foo(String s) { System.out.println("foo(String)"); } void bar(Object o) { foo(o); } public static void main(String[] args) { (new DispatchTest1()).bar("What gets run?"); } } class DispatchTest2 { static class A { void foo() { System.out.println("A.foo()"); } } static class B extends A { void foo() { System.out.println("B.foo()"); } } void bar(A a) { a.foo(); } public static void main(String[] args) { (new DispatchTest2()).bar(new B()); } } What about this one? Dispatch class DispatchTest1 { void foo(Object o) { System.out.println("foo(Object)"); } void foo(String s) { System.out.println("foo(String)"); } void bar(Object o) { foo(o); } public static void main(String[] args) { (new DispatchTest1()).bar("What gets run?"); } } class DispatchTest3 { static class A { static void foo() { System.out.println("A.foo()"); } } static class B extends A { static void foo() { System.out.println("B.foo()"); } } void bar(A a) { a.foo(); } public static void main(String[] args) { (new DispatchTest3()).bar(new B()); } } How about now? Object-oriented implementation ● Dispatch – Static dispatch: all method calls can be resolved at compile time – Dynamic dispatch: polymorphic method calls resolved at run time – Single vs. multiple dispatch (one object’s type vs. multiple objects’ type) ● Class instance record – List of member variables for objects w/ vtable pointer – Subclass CIR is a copy of the parents' with (potentially) added fields ● Virtual method table (vtable) – List of methods w/ pointers to implementations Heap Static Code Section vtable ptr foo Parent::foo x : int bar class instance record virtual method table Child::bar Object-oriented implementation public class A { public class B extends A { public int x, y; public int z; public void draw() { … } public void draw() { … } public int area() { … } public void sift() { … } } } a = new A(); b = new B(); Heap Static Code Section A a vtable ptr draw A::draw x : int area A::area y : int virtual method table class instance record B B::draw b vtable ptr draw B::sift x : int area y : int sift z : int Dynamic dispatch! Multiple inheritance class A { public: class C : public A, public B { int x; public: virtual void init() { … } int z; virtual void foo() { … } virtual void foo() { … } } virtual void baz() { … } class B { } public: int y; virtual void bar { … } c = new C(); } Heap Static Code Section C (C & A part) c vtable ptr init A::init x : int foo A::foo vtable ptr baz y : int C (B part) B::bar z : int bar C::foo C::baz Multiple inheritance ● Diamond problem – If D inherits from B and C with common ancestor A, and all except D implement method “foo,” which is called? class D : public B, C { public: A void bar() { foo(); // which foo? foo() } } B C C++ solution: use ordering from definition foo() foo() (so B’s foo here) Java solution #1: only inherit multiple interfaces D (so no foo here) bar() Java solution #2: compiler error (Java 8 adds default methods for interfaces) Inheritance and the stack ● How to handle class instance records on stack in case of copying to a superclass variable? – No space for subclass data – Object slicing: remove subclass data – Causes a loss of information! class A { int x; } class B inherits A { int y; } B b = new B(); A a = b; // copy; A’s CIR is smaller // b.y is lost! // no way to cast a back Templates vs. generics ● Templates (C++) – Compiles different versions w/ mangled names ● Generics (Java) – Type erasure: compiler changes generic type to Object and inserts runtime casts (expensive!) – No runtime difference between HashSet<String> and HashSet<Integer> ● Example: no arrays of generics (array members must be type-checked at runtime) – Only one set of static member data template <class T> class Foo<T> { class Foo { T data; T data; void bar(T x) { public: this.data = x; void bar(T x) { } this.data = x; } } } Templates in C++ Generics in Java Reflection ● A language with reflection provides runtime access to type and structure metadata – Sometimes with the ability to modify the structure – Often incurs a severe runtime penalty because of data structures required ● Examples: – Ruby: methods and send – Java: java.lang.Class and java.lang.reflect.Method try { "Hello".send( System.out.println("str".getClass() .getMethod("toUpperCase") "str".methods .invoke("Hello")); .grep(/upcase/)[0]) } catch (NoSuchMethodException ex) {} catch (IllegalAccessException ex) {} catch (InvocationTargetException ex) {} Reflection in Ruby Reflection in Java History of OOP ● Simula (1967): data abstractions for simulation and modeling ● Smalltalk (1980): objects and messages ● C++ (1985): originally “C with classes” ● Java (1995) and C# (2000): goal was “C++ but better” ● Ruby (1996): pure, dynamic OOP language ● Most modern languages have some form of OOP – Abstract data types – Inheritance – Dynamic binding Abstraction in C ● Structs for encapsulation ● void* pointers for polymorphism and inheritance ● Stack or heap allocation (manual management) ● Header file and implementation file ● Function pointers for dynamic dispatch ● No reflection by default https://www.cs.rit.edu/~ats/books/ooc.pdf Abstraction in C++ ● Classes and structs ● Stack or heap allocation ● Manual memory management: constructors and destructors ● Header file and implementation file ● Visibility: public (default for structs) or private (default for classes) – "Friend" functions for private access outside class ● All forms of polymorphism (parametric via templates) ● Static dispatch by default (override via “virtual” keyword) ● Multiple inheritance w/ resolution via inheritance order ● Namespaces for naming and encapsulation ● No reflection by default Abstraction in Java ● Classes similar to C++ ● Single inheritance tree (rooted at Object) ● No stack allocation (everything on heap) ● Automatic memory management ● Visibility modifiers required (public,

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    26 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us