Computer Specialist Review Session 3 – Raymond Law Topics Covered In This Course Database Software Development Process Web Applications Object Oriented Programming Basics Data Structures & Programming Principles Object Oriented Programming Object Oriented Benefits Data over Function (Modeling Data) Code Reuse and Recycling Encapsulation & Information Hiding Prevents programmers from touching things they shouldn't Force More Time Designing Decoupling of System Why Decouple A change in one module usually forces a ripple effect of changes in other modules. Assembly of modules might require more effort and/or time due to the increased inter-module dependency. A particular module might be harder to reuse and/or test because dependent modules must be included. Objects & Classes Objects can be thought of as collections of related data treated itself as a single larger piece of data. Classes are the definition or blueprint for any particular object. class car { string engine_status; int fuel; } Objects & Classes We can create instances (copies) of each object which will be independent from another. Each of these instances are objects based on a class. Johns_car = new car(); Aprils_car = new car(); In this case we have created two car objects in memory. Each car has its own independent engine_status and fuel attribute Objects & Classes Johns_car -engine_status -fuel Aprils_car -engine_status -fuel Objects & Classes Instance variables, individual variables residing inside of an object can be modified. Johns_car.fuel = 25; Johns_car.engine_status = 'good'; Aprils_car.fuel = 30; Objects & Classes Johns_car -engine_status = 'good' -fuel = 25 Aprils_car -engine_status -fuel = 30 Inheritance Inheritance is a feature of object oriented languages that allows for code reuse and extensibility of classes. class car { string engine_status; int fuel; } class limo extends car { int max_passengers; } If I create an object of class limo it will have everything car has and more because limousine inherits from car. Objects & Classes Johns_car -engine_status = 'good' -fuel = 25 Julias_car = new limo(); Julias_car.engine_status = 'new'; Julias_car.fuel = 50; Julias_car.max_passengers = 10; Aprils_car -engine_status -fuel = 30 Julias_car -engine_status = 'new' -fuel = 50 -max_passengers = 10 Methods Vs. Functions A function is a piece of code that is called by name. It can be passed data to operate on (ie. the parameters) and can optionally return data (the return value). All data that is passed to a function is explicitly passed. A method is a piece of code that is called by name that is associated with an object. In most respects it is identical to a function except for two key differences. Instance Methods Instance methods are functions that have access to all instance variables. They are primarily used as an interface for how to interact with the object. For instance lets say you are building a simulation where fuel is a precious resource, you do not want the user to be able to interact with the fuel variable directly, instead they will access it through defined functions like drive() and refuel() Instance Methods class car { string engine_status; int fuel; function drive(int distance){ if(fuel == 0) return 0; fuel = fuel - distance/30; return distance; } function refuel(int amount){ if(fuel + amount > 30) fuel = 30; else fuel = fuel + amount; } } Instance Methods Johns_car -engine_status = 'good' -fuel = 25 +drive(int distance) +refuel(int distance) Aprils_car -engine_status -fuel = 30 +drive(int distance) +refuel(int distance) Julias_car -engine_status = 'new' -fuel = 50 -max_passengers = 10 +drive(int distance) +refuel(int distance) Subtype Polymorphism As you can see Julia's car also received the added drive and refuel functions. This is called subtype polymorphism (often shorten to polymorphism) If A is a subtype of B, an instance of A can do anything an instance of B can do. When created they get all instance variables and methods This does not work in the reverse. Subtype Polymorphism class limo extends car { string moon_roof = 'closed'; function open_moon_roof(){ moon_roof = 'open'; } function close_moon_roof() { moon_roof = 'closed'; } } It is not possible for John or Aprils car to call methods open_moon_roof() or close_moon_roof() because they are exclusive to the limo class. It is fine for Julias_car to call them because it is of the limo class, in addition her car can use drive and refill because limo extends car. Abstract Classes Abstract Classes are classes of objects which can not be instantiated directly. They only exist to be inherited from. class vehicle { int tires; } class car extends vehicle{ string engine_status; int fuel; } class bike extends vehicle{ string tire_condition; function ring_bell(); } Object Composition class small_garage{ car parkingspot1; car parkingspot2; string toolbox; int spareTires; } Jims_Garage = new small_garage(); Jims_Garage.parking_spot1 = Johns_car; Jims_Garage.parking_spot2 = Julias_car; Jims_Garage.toolbox = 'new'; Jims_Garage.spare_tires = 8; Object Composition Jims_Garage parking_spot1 Johns_car -engine_status = 'good' -fuel = 25 +drive(int distance) +refuel(int distance) parking_spot2 Julias_car -engine_status = 'new' -fuel = 50 -max_passengers = 10 +drive(int distance) +refuel(int distance) toolbox = 'new' spare_tires = 8 Aprils_car -engine_status -fuel = 30 +drive(int distance) +refuel(int distance) Object Composition – List Structure class infinite_garage{ car parkingspot; infinite_garage next; function addCar(park_this_car){ if(parkingspot == null) parkingspot = park_this_car; else if(next == null) { next = new infinite_garage(); next.addCar(park_this_car); } else next.addCar(park_this_car); } } King_Corp_Garage = new infinite_garage(); Jims_Garage.addCar(Aprils_car); Object Composition – List Structure King_Corp_Garage parking_spot Aprils_car -engine_status = 'good' -fuel = 25 next parking_spot next Another_car -engine_status = 'damaged' -fuel = 25 parking_spot next Encapsulation & Data Hiding You can designate which variables and methods are allowed to be called directly using keywords public and private. If a variable or method is marked as public it can be interacted with directly. If a variable or method is marked as private it can be interacted with only through instance methods. This allows users to separate the object we are trying to model and how the internals works. We can use the public car methods drive() and refill() without understanding what it does inside the variable. This is useful because it prevents the external code from being concerned with the internal workings of an object. Encapsulation & Data Hiding class car { private string engine_status; private int fuel; public function drive(int distance){ if(fuel == 0) return 0; fuel = fuel - distance/30; return distance; } public function refuel(int amount){ if(fuel + amount > 30) fuel = 30; else fuel = fuel + amount; } } Encapsulation & Data Hiding Aprils_car = new car(); Aprils_car.drive(60); Aprils_car.refuel(10); Aprils_car.engine_status = 'perfect'; Aprils_car.fuel = 999; Creating Safety Through Encapsulation Having allowed public methods like refuel() allow you to keep instance variables like fuel in a consistent state. class car { private string engine_status; private int fuel; private int max_fuel_capacity; public function refuel(int amount){ if(amount < 0){ print("Error: Cannot Refuel Negative Amount"); return; } if(fuel + amount > max_fuel_capacity) fuel = 30; else fuel = fuel + amount; } } Special Methods - Constructors A constructor is a special function that is called whenever a car is instantiated. Special Methods - Constructors class car { private string engine_status; private int fuel; private int max_fuel_capacity; public function car(){ engine_status = 'new'; fuel = 30; max_fuel_capacity = 30; } public function car(int max){ engine_status = 'new'; max_fuel_capacity = max; fuel = max; } } Special Methods - Constructors Franks_Car = new Car(); Donalds_Car = new Car(50); Special Functions - Constructors Franks_Car -engine_status = 'new' -fuel = 30 -max_fuel_capacity = 30; Donalds_Car -engine_status = 'new' -fuel = 50 -max_fuel_capacity = 50; Special Methods - Abstract Methods Abstract classes are classes that you can not instantiate directly Abstract methods are functions that must be declared if a class plans to use inheritance although is not defined in the parent class. Special Methods - Abstract Methods class motor_vehicle { int fuel; abstract function drive(int distance); } class car extends motor_vehicle{ function drive(int distance){ fuel = fuel - distance/30; } } class truck extends motor_vehicle{ function drive(int distance){ fuel = fuel - distance/10; } } Special Methods – Overriding Methods An inherited class has the ability to redefine methods even for non-abstract methods. class Animal { print() { print "This is an Animal" ; } } class Cat extends Animal { print() { print "This is a Cat" ; } } Class Variables Class variables have one copy of the variables shared with all instances of the class. class car{ static int car_count = 0; public car(){ … car_count++; } } car_count in this case would be shared between all instances of car, everytime I create a new car with the constructor my car_count goes up by one. Special Methods – Class Methods Class methods are methods that are not bound to an object, but to a class. If a function does not need any data from the instance you can mark that function as a class method. Class methods can not access instance variables. They can access class variables however. Special Methods – Class Methods class car{ … private static int car_count = 0; public function car(){ … car_count++; } static function print car_count(){ print car_count; } } Data Structures Data Structures Data Structures (Abstract Data Types ADT) are used to organize data so it can be accessed quickly and usefully. Data Structures provides a means to manage large amounts of data efficiently Different problems can be represented using various data structures, some more optimally than others. Data Structures Basic Intermediate Array Lists Stacks Queues …. Trees Heaps / Priority Queue Hash Tables … Advanced AVL Trees Directed acyclic graph DAGs Hypergraphs … Data Structures Different Data Structures are useful for different tasks and support different set of operations. Each has its own benefits and drawbacks When considering each data structure the most important part is what operations it supports. This is in essence how you can interact with it. Stack A stack is a LIFO (Last In First Out) data structure Supported Operations: Push() – adds an element to the top of a collection Pop() – removes the most recently added element not yet removed. Stack class pancakeFrame(){ pancake pancake_data; pancakeFrame next; } class pancakeStack(){ pancakeFrame top; function push(pancake_to_add){ newtop = new pancakeFrame(); newtop.pancake_data = pancake_to_add newtop.next = top; top = newtop; } function pop(){ if(top == null) report "Error Trying to Remove From Empty Pancake Stack"; toRemove = top.pancake_data; top = top.next; return toRemove; } } Extending Our Data Structure function empty(){ if(top == null){ return true; } return false; } function peek(){ if(empty()) return null; toReturn = pop(); push(toReturn); return toReturn; } Queue A stack is a FIFO (First In First Out) data structure Supported Operations: Push() – adds an element to the back of a collection Pop() – removes an element from the front of the queue. Scheduling Jobs FIFO and LIFO are also used in job scheduling to determine what jobs to do next. FIFO (FCFS) – First Job to come in gets worked on. LIFO – Most recent job entered gets worked on. Other Scheduling Systems RR – Round Robin – Based on the concept of time slicing, giving all jobs a single unit of processing time arranged in a cyclic order. After a cycle is completed, restart from the top. SJF , SJN – Shortest Job First (Shortest Job Next) SRTF – Shortest Remaining Time First DeQueue Double-ended Queue Supported Operations: Push_front(data); Push_back(data); data Pop_back(); data Pop_front(); List Data Structure used to represent ordered data in a sequence. Supported Operations: isEmpty() Prepend(data) Append(data) list{ object data; list next; } Trees A class of data structure used to simulate hierarchical data. Has a root and subtrees of children each of which has a parent node. Common Operations: Searching Enumerating Insertion Deletion Runtime Consideration When choosing a particular data structure, you want to consider the data you are trying to model and the operations that the data will be using frequently. Lists can insert very fast, but have a very slow search. Tree structures have very quick search and sorting methods, but at the cost of extra space requirements Hash tables have fast Insert, Lookup and Delete methods, but finding neighboring data is difficult. Sorting the data is also not easily accomplished. Graph data structures on the other hand are really quick for finding neighboring data.