CSC207 Notes

CSC207 Notes

Lecture Notes

Click to show lecture material

## Object oriented programming ### Features - Abstraction: the essential characteristics of something - Encapsulation: - putting data together with methods to manipulate it - hiding how it all works behind the schenes - Inheritance: subclasses getting features of another class - Polymorphism: - an expression can take on different things - e.g. method calls that have different types as an inputs ### Coupling and cohesion - coupling: how closely two classes are linked - high coupling: changes to one class means a lot of changes in other classes - low coupling: changes to one class shouldn't affect others too much (this is preferred!) - cohesion: how closely related features of a class are - high cohesion: methods are strongly-related (this is preferred!) - low cohesion: methods are not that related and don't seem to make that much sense as a package together ### Design principles - techniques for making programs easy to read, **hard to break**, maintainable, and efficient (for people) ### SOLID design: - **S**ingle reponsibility principle: A class should have one, and only one, reason to change - **O**pen/closed principle: Classes should be open for extension but closed for modification - **L**iskov substitution principle: Subclasses should add to a base class’s behaviour, not replace it - **I**nterface segregation principle: Many client-specific interfaces are better than one general-purpose interface - **D**ependency inversion principle: - high-level code shouldn’t depend on low-level code, both should depend on abstractions - abstractions shouldn’t depend on details, details depend on abstractions

PCRS Quest 1

Click to show Quest 1 material

## Hello World - no code exists outside a class - there are no functions, but methods exists public static void main(String[] args){} - when a class is run, this method is automatically called - public declares what has access to that object ```java System.out.println(5+7); ``` - System is the class - out is a static member in the class - println is a method within that member - 5+7 is the expression ## Variables ```java int i; //default value for int is 0 Object obj; //default value for any object is null String name = "CSC207"; //note the capital 'S' and double quotes boolean isTrue = false; //lowercase boolean values (true/false) double gpa = 0.0; ``` ## Errors: ```java number = 42; //didn't declare variable int i = 19.22; //type mismatch: can't convert double to int int i = 1; int i = 2; //duplicate local variable ``` ## References vs Primitives - Java has **primitive** and **reference** types - primitive types directly hold values, while reference types point to values - primitive types start with lower case letters (int, boolean, etc) - reference types start with upper case letters (String, etc) can call using String s1 = new String("..."); - call stack keeps track of what method we're running - object space is where objects are stored - static space is where static members of a class are stored - string variables from the call stack get an id referencing the String object in the object space ## Strings pt 1 - Strings are immutable (can't ever change a String variable once created, but can perform operations on it) ```java String s3 = s2 + s1; //add two strings to make a new one char c = s1.charAt(2); //get the character at index 2 s1 = s1.substring(2, 4); //slice a string (like s1[2:4]) s1 = " I am a string . "; s1 = s1.trim(); //get rid of extra spaces ``` - other methods: length, startsWith, indexOf, etc... - for mutable strings: ```java StringBuilder sb = new StringBuilder("hi"); sb.append(" world."); //now contains "hi world." sb.insert(2, " there"); //now contains "hi there world." sb.setCharAt(14, '!'); //now contains "hi there world!" //(note single quotes for char) sb.reverse() ``` - adding Strings can be slow because it creates a whole new string each time - appending to StringBuilders is faster because it modifies an existing one ## Strings pt 2 ```java String a = new String("abcd"); String b = new String("abcd"); System.out.print(a == b); //prints false because a and b have been declared as 'new' ------------ String a = "abcd"; String b = "abcd"; System.out.print(a == b); //prints true because Java tries to reuse string locations // and sets 'b' to point to same spot as 'a' ------------ //all of these are valid initializations String a = "hello"; String a = new String("hello"); String a; a = new String("hello"); String a; a = "hello"; ------------ String a = "hi"; a = "hello"; //NOT valid ``` ## Classes ```java int i = ___; String val = String.valueOf(i); //turns an int to a string System.out.println(Integer.BYTES); //prints the number of bytes of an integer ``` - automatic de-allocation when variable doesn't refer to anything, don't need to free anything - can explicitly de-allocate by setting a variable to null ## Arrays - array length can't be changed - all elements must be of the same type - arrays are reference types, not primitive types ```java //an array of ints, nums is a variable that refers to the array int[] nums; /all indices contain default value, 0 nums = new int[5]; int[] nums = {1,2,7,109,888}; //array holds {1,2,7,109,888} nums[1] = 81; //array holds {1,81,7,109,888} ``` - no negative indices, no slicing - add different types into same array: ```java Object[] rand = new Object[5]; rand[0] = new String("hello"); rand[1] = new Integer(1000); rand[2] = new Monster("Fred"); //array inside an array rand[3] = new int[50]; //add the first element into another variable Object element = rand[0]; //DOESN'T WORK, even if rand[0] is a string String element = rand[0]; //works if rand[0] can be typecast to a string String element = (String)rand[0]; int[][] table; // 2D array ``` ## Alias - can only create an alias with a MUTABLE reference type (primitives don't create objects) - If object is immutable (e.g. strings), changing string creates a copy - if alias object changes, original still points to it - careful with double & farther aliases (e.g. array of array of strings) - primitive types are compared by VALUES and class types are compared by REFERENCES ## Control Structures ```java if (variable > 500){ doStuff(); } else if (variable > 400) { doOtherStuff(); } else { doMoreStuff(); } if (variable > 500) doStuff(); //good for one line inside only while (variable > 500){ variable -= 1; } for (initialization; termination; increment){ //do stuff here } for (Object item : listOfItems){ //do stuff } do { //makes sure loop will run at least once //stuff } while (condition); //note semicolon ``` ## While loops ```java i++; //checks value, then increments ++i; //increments, then checks value while(array[i++] < 7) //... ``` ## Classes - two types of variables declared outside method: instance and class variables - instance vars: come into existance when a new object of that class is constructed - class vars: shared by all instances of a class (denoted by saying 'static') - constraints (for values, relationships, etc) should be recorded - MUST hold true before (assumed) and after (check!) a method runs - constructors have same name as class and are called automatically - NO return type (not even void) - can overload constructors (to make multiple!) - to call other constructors, call 'this(arguments_here)' - if NO constructors are supplied, Java makes a no-arg default constructors - better to make 'getter' and 'setter' methods than to make variable public - this allows the API to change, but the user to use it the same - use '@Override' then method itself to recreate a method ```java @Override //overrides original toString method, and allows tweaking of it public String toString(){ //... } //SHOULD ALSO OVERRIDE HASHCODE (didn't in this case) @Override //redefines what equals means for this class public boolean equals(Object obj){ //test if 'this' is the same as 'obj' by some method } ``` ## Parameters - when a method is called: - new stack frame is added to stack - parameters are defined on the stack frame - value in each argument is assigned to its parameter - parameters vs arguments: - each variable in a method definition is a parameter - each variable in a method call is an argument - each argument passed to a method tries to create an alias - for primitives, just copies value, for reference, it mutates values

PCRS Quest 2

Click to show Quest 2 material

## Overloading - two methods that have the same name but different parameters - one can be a default, and the other can call it, or they can process inputs differently, etc - must be inside the same class - interfaces are clearer to work with ## Static - means you can have (for example) one variable that each instance of a class shares - make good counters, etc - kind of like global variables, but better - static variables can be inside any methods - regular variables CANNOT be inside static methods ## toString and equals - toString has an default method already created for each object - can create your own toString method that overrides default - all object types have a toString method - equals has a default method already created for each object - like toString, can override default - hashmaps can map an object to a list ## Equality (== vs. equals) pt 1 - '==' checks if references are the same - 'equals' checks if the content is the same - every class has an equals method (defaulted to checking identities if you didn't declare it) - **string interning** is where Java saves space by using only one object for each distinct string - calling 'new' creates a new version of that string - Something to think about: If declaring two new strings, and then a third not-new one, which one is reused? ```java String s1 = "ice cream"; String s2 = "ice" + " " + "cream"; System.out.println(s1 == s2); //prints true ``` ## Comparator and Comparable - can use '.sort' on any array of comparable types ```java public static void sort(Object[] a){} //the sort method (default) ---------- //to let sort do its job, need to implement the below: //to have comparability, must also have the class implement: class ClassName implements Comparable { //comparable stuff in here int compareTo (ClassName o){ //return negative if less than //return 0 if equal to //return positive if greater than } } ``` - implements Comparable rather than Comparable since this class can be compared to any object of ClassName - to add functionality for comparing by different fields: ```java //in the ClassName class, define the method int compare(ClassName c1, ClassName c2){ //compare somehow here (default comparing) } //add another class to compare by another field import java.util.Comparator class SpecificFieldComparator implements Comparator{ @Override public int compare (ClassName c1, ClassName c2){ //compare by that specific field } } //then from main program, can call sort using: Arrays.sort(array_name, new SpecificFieldComparator()); ``` ## Inheritance - extends vs implements? ```java class BigClass { private int bigInt; public BigClass(int newInt){ bigInt = newInt; } //stuff in here } class SmallerClass extends BigClass { private int smallInt; public SmallerClass(int newIntSmall, int newIntBig){ super(newIntBig); //call constructor of BigClass with this value smallInt = newIntSmall; //initialize our new variable too } //note that bigInt is private so we do not have access to it here //to change the value of bigInt, must call a method from BigClass that has access } ``` This is also valid: ```java class BigClass{ private int bigInt; public BigClass(){} public BigClass(int newInt){ bigInt = newInt; } } //automatically calls BigClass() as the constructor, don't need to add 'super()' class SmallerClass extends BigClass{ public SmallerClass(){} } ``` </p></details>

Author face

Nyah Way

Computer science specialist and the University of Toronto alumni, now pursuing her full-time career at Google.

Other things I've done: