diff --git a/README.md b/README.md index 0c34b92..e4b2e4c 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,24 @@ [WEEK ONE](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-one.md) - [WEEK TWO](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-two.md) + +[WEEK THREE](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-three.md) + +[WEEK FOUR](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-four.md) + +[WEEK FIVE](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-five.md) + +[WEEK SIX](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-six.md) + +[WEEK SEVEN](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-seven.md) + +[WEEK EIGHT](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-eight.md) + +[WEEK NINE](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-nine.md) + +[WEEK TEN](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-ten.md) + +[WEEK ELEVEN](https://github.com/ruthrootz/java-oop-class-notes/blob/main/week-eleven.md) + +[FINAL EXAM](https://github.com/ruthrootz/java-oop-class-notes/blob/main/final-exam.md) diff --git a/callback-methods.png b/callback-methods.png new file mode 100644 index 0000000..3be62fb Binary files /dev/null and b/callback-methods.png differ diff --git a/complexity.png b/complexity.png new file mode 100644 index 0000000..af65290 Binary files /dev/null and b/complexity.png differ diff --git a/final-exam.md b/final-exam.md new file mode 100644 index 0000000..fc5b1e5 --- /dev/null +++ b/final-exam.md @@ -0,0 +1,79 @@ +# final exam topics + +## essay questions +- Value of implementing data structures and code reuse. These questions are sort of ‘in your opinion’ questions and what I would be looking for is to use your knowledge of those topics and provide to me a response of a particular question. No coding required for those two questions. + - data structures: These are tried-and-true structures that are implemented in the most efficient way that has been discovered so far! Almost all big modern languages already have implementations of these structures. Most programmers know how to use them, so using them increases code clarity when someone reads the code using these structures. Some problems are uniquely suited to these structures as well. Scheduling tasks, for example, works just like a queue does, making it a perfect problem to use queues for. Using these out-of-the-box implementations also aids with code-reuse... +- Know... + - the ‘Shunting-yard algorithm’ + - infix: 3 + 7 * 2 - 8 / (6 - 2) + - postfix: 3 7 2 * + 8 6 2 - / - + - steps + - add each number to the stack, one by one + - when you reach an operator, pop off the two top numbers, perform the operation, and add the result back to the stack + - there should be only one number on the stack at the end, and that's the answer to the problem + - the idea of semaphores + - the shortest path algorithm + - the structured programming movement + - make code as modular as possible so that it's clear and easy to modify + - elements: control structures, subroutines, blocks + +## short answer questions +1) `Queue` principles +2) Adapter design principles +3) Decorator design pattern principle +4) `ArrayList` principles +5) `LinkedList` principles +6) Know your interfaces and what they do: `Iterator`, `Iterable`, `ListIterator`, `Collection`, `List`. +7) Know time complexity for `Array`, `List`, `Stack`, `Queue`. +![time complexity](complexity.png) + +## multiple-choice +1) ArrayList and LikedList efficiencies - efficiencies for removing, adding, etc. +2) Choose best collection to apply to a given situation: storing payroll calculations, program to track progress in a maze, keeping track of customers in alphabetical order, driving dispatching system like Uber. + +Basically make sure you know the ins and outs of the following data structures: `ArrayList`, `LinkedList`, `Queue`, or `Stack`. + +## coding problems + +### Decorator Pattern problem +1) Description: Need to create a system to allow for basic seat reservations and decorations for adding wifi. +2) You're given a UML diagram where you'll need to implement a few classes. +3) What you need to do is to look at the UML diagram and simply implement the methods using the decorator method. +4) You will be given a sample of what your output should look like. +5) You will be given a `RunMe.java` file with starter code. +Go over what the Decorator classes do: +1) Remember to declare your main object, `FlightSeat`. +2) Then just code up your getters and remember to instantiate the constructor for the classes extending the decorator classes. +3) Call the super class (`FlightSeatDecorator`) and do your modifications locally. + +### Stacks problem +1) Description: The given problem is about balancing parentheses, obviously you have to make sure each parentheses has its open and respective closed parentheses. +2) Example: [{}], {}, ([{}]) are balanced, [{}, {, ({) are NOT. +3) Using a stack you need to check if a particular string is balanced or not. Return a `true` or `false`. +4) Tips: perhaps a string of opening strings, like {({. +5) Have a string of closing strings like })]. +6) What you need to do is to iterate through the tokens. +7) If the tokens are starting strings then push to the stack. +8) If not then see that means it is an ending string so see if that particular string matches the top of the stack. +9) Work your way through the rest of the tokens. +10) Return false if any of the above steps don't work. +11) If the stack is empty then you know it's true, so return that. +12) Conclusion: know how stacks work and know your stacks methods: `empty()`, `push()`, `pop()`. + +### Queues problem +1) Description: Need to implement a publish/subscribe model (like YouTube, etc.) by implementing two classes. +2) Will be given a UML diagram for the methods and variable for each class you need to implement. There are links to APIs you may need embedded in the specification. +3) You will be given a Queue object of a particular class will need to do such things as reading and removing oldest notifications (`poll()`), getting number of notifications (`size()`), +check if two subscribers are equal. +4) Conclusion: pretty simple problem, know how to use poll and size methods of queue. + +### Lists problem +1) Description: Implement two methods using the `List` class. Links to the applicable Java API docs will be available. +2) You will do the following: +- Reverse a list in place in O(n) time, should not need to create any new lists. +- Merge two sorted lists in O(n+m) time. Same as what was done in the polynomial homework. Result should be ordered ascending. +3) Need to know the following interfaces: `List` and `ListIterator` methods and understand what they do. +3) So how do you reverse a list? Possibly have two list iterators from `List` class and iterate between both lists with one iterator starting from the end? +4) How do you merge a list? May need to do some comparisons. Again call list iterator from each list. +5) How do you declare a `ListIterator` obj? `ListIterator blah = somelist.listIterator();` +6) Then manipulate blah to do the merge operation. You're comparing each letter in each list to see if one comes before the other in alphabet and take that one and add to result. diff --git a/week-eight.md b/week-eight.md new file mode 100644 index 0000000..e69de29 diff --git a/week-eleven.md b/week-eleven.md new file mode 100644 index 0000000..dec92e2 --- /dev/null +++ b/week-eleven.md @@ -0,0 +1,17 @@ +## queues +- queues are FIFO structures (first in, first out) +- they're an array of elements where you can only add to the end and remove from the beginning +- examples of real-world queues include people waiting in a checkout line +- queues are most often used in scheduling algorithms + - particularly in scheduling algorithms that deal with Poisson-distributed events +- methods that queues (should) implement + - `bool queue(E data)` adds `data` to the end of the array + - `E enqueue()` removes and returns the first element in the array + - `E peek()` returns the first element in the array without removing it + - `bool isEmpty()` tells whether the array has any elements in it (obviously) +- `LinkedLists` are the best structure to use to implement queues + - it's fast to add to the end of them + - and fast to remove from the beginning + - because of the head and tail nodes + - `ArrayLists` are only fast to remove/add to the end (O(1)) + - any operation at the beginning of an `ArrayList` will be an O(n) operation diff --git a/week-five.md b/week-five.md new file mode 100644 index 0000000..94b6399 --- /dev/null +++ b/week-five.md @@ -0,0 +1,53 @@ +## Compare and contrast iterative versus sequential software lifecycle approaches. +- steps in SDLC: requirements analysis, design, development, testing, production, maintenance +- waterfall model + - phases + - requirements analysis: what should the product do? + - design + - what are the business rules? + - user stories are written at this point + - development + - what technologies will it use? + - what software design patterns? + - actual coding! + - testing + - unit testing + - integration testing (how all the modules work together) + - user testing (how long does it take user to complete tasks?) + - regression testing + - white box testing: testing the code while knowing about the code and how it works (unit testing) + - black box testing: testing the code as a user would use it, not knowing about how the code is working + - production + - maintenance + - change requests + - bug reports + - software spends most of its time here + - disadvantages + - costly to fix bugs + - slow + - not flexible + - produces software that isn't actually what the user wants +- spiral (scrum, agile) model + - uses short sprints + - each sprint goes through all the steps of SDLC + - adaptable to change + - build products incrementally + - gets user feedback regularly + - disadvantages + - complex process + - difficult to estimate + - not easy for project managers + +## Use UML class diagrams to illustrate relationships between classes. +- identify classes by finding the nouns in the requirements analysis +- identify methods by finding the verbs +- identify interfaces by looking for adjectives (?) + +## Use CRC cards to capture the responsibilities of each class and the relationships between classes. + + +## Use primitive operation counts and deductive reasoning to determine the efficiency of algorithms. + + +## Given a set of initial conditions, predict how the runtime of an algorithm is affected by increased input size + diff --git a/week-four.md b/week-four.md new file mode 100644 index 0000000..7161308 --- /dev/null +++ b/week-four.md @@ -0,0 +1,67 @@ +## Explain the purpose and use of exception handling for error detection and correction. +- exception handling is used when the point at which an exception occurs is different from the point at which that error can or could have been corrected +- uncaught exceptions terminate the program +- the place where an exception is thrown is always different than the place it gets caught + - because you can't or don't want to fix the error in the same place where it happened + +## Differentiate between checked and unchecked exceptions. +- unchecked exceptions are exceptions that happen during runtime + - unchecked exceptions are subclasses of `RuntimeException` + - they happen due to programmer error + - the programmer can write code to avoid these exceptions +- checked exceptions are exceptions that are explicitly thrown in the code + - checked exceptions are subclasses of `Exception` + - they account for things that happen that are outside of the programmer's control + - all checked exceptions must be caught or declared to be thrown + - `throws` is used to show that a method throws checked exceptions + - `public void someMethod() throws FileNotFoundException, SomeOtherCheckedException` + - wherever the function is called, it has to either be in a method that is marked with `throws` or it has to catch the exception/s + +## Use the keywords throws, try, throw, catch, and finally to implement exception handling. +- `throw` indicates you've found an error, something that you can't fix +- `try` blocks wrap code that _might_ throw an exception +- you can then `catch` exceptions in the catch block +- a caught exception doesn't terminate the program +- you can chain `catch` blocks to catch specific exception types + - when chaining, you have to put the catch blocks in order of most to least specific exception types + - e.g., put `IOException` after `FileNotFoundException` because `FileNotFoundException` is a subclass of `IOException` + - if you caught them in the other order, `IOException` first, all `IOExceptions` _and_ `FileNotFoundExceptions` would be caught by the first block (`IOException`), since `FileNotFoundException` _is an_ `IOException` +- the `finally` block always runs, whether an exception was thrown or not +``` +try +{ + var result = methodThatMightThrowException(); +} +catch (SomeExceptionType e) +{ + // handle error here +} +catch (RuntimeException e) +{ + // handle error here +} +finally +{ + // this code will run no matter what +} +``` + +## Define and use a domain-specific exception hierarchy. +- **???** + +## Read and write binary files. +``` + +``` + +## Read and write text files. +- line endings in Unix- vs. Windows-based machines + - Windows machines end lines with `\r\n` + - Unix-based machines end lines with just `\n` +``` + +``` + +## Read and write serialized object files. +## Define and explain the Serializable interface +## Distinguish between random and sequential access files. diff --git a/week-nine.md b/week-nine.md new file mode 100644 index 0000000..3c599d8 --- /dev/null +++ b/week-nine.md @@ -0,0 +1,23 @@ +## decorator pattern +- a decorator class implements some interface + - it _is an_ [insert interface name here] +- BUT it also _has an_ instance of that interface +- "decoratee" is the instance of the interface that the decorator class has +- if you extend the decorator class... + - instances of this concrete class can make the instance in the decorator class _immutable_ + - IF you `@Override` all the methods that modify the decoratee + - this way you can safely make an instance of the concrete decorator that has an immutable [insert interface name here] +- any subclasses the interface requires must also be decorated, both in the decorator class and any concrete classes that extend the decorator + +## decorator example (from Dr. Whittaker) +- `CollectionDecorator` + - the decorator class itself + - implements `Collection` + - has an instance of `Collection` called `decoratee` + - also has a subclass `IteratorDecorator` that implements `Iterator` and has an instance of `Iterator` +- `UnmodifiableCollection` + - extends `CollectionDecorator` + - overrides all of its methods + - leaves methods that modify the collection unimplemented (i.e. they throw `Unimplemented` exceptions) + - also has a subclass `UnmodifiableIterator` that extends `IteratorDecorator` + - the iterator methods that modify the collection (`remove`, `add`, etc.) throw `Unimplemented` exceptions diff --git a/week-one.md b/week-one.md index 502b90f..e95ac12 100644 --- a/week-one.md +++ b/week-one.md @@ -1,4 +1,4 @@ -### inheritance +## inheritance - what it is - a hierarchy of classes, each one defining a more specific subset of the parent class (or "superclass") - the subclass "is a" version of the superclass @@ -38,7 +38,7 @@ vehicle - parent methods and properties need to be `public` for them to be accessible in subclasses (or by actual instances of the subclass) - every class implicitly extends Java's base Object class; Object is the parent class of all classes -### override and overload +## override and overload - override (decorator: `@Override`) - you're "overriding" when you make a method with the same name and signature of a method in the superclass - when called by an instance of the subtype, the subtype/overridden version of the method will be run @@ -49,7 +49,7 @@ vehicle - within the same class, you can have multiple versions of the same method - the return types and names must be the same, but the types, number and order of the parameters can be different -### polymorphism +## polymorphism - what it means - you can call the same methods and/or use the same logic with objects of different types - a different method is called depending on the type of the object @@ -57,11 +57,16 @@ vehicle - an object gets its type checked and then the correct override of a method is chosen and invoked - this happens dynamically, during runtime -### late binding -- what it is - - **???** +## late binding +- this is when ther JVM determines the type of an object during runtime + - say you have an interface `Comparable` and classes `Blanket` and `Lightbulb` that implement it + - `Comparable` defines a method `compareTo()` that is obviously written differently in each subclass + - lastly, you have a class that uses `Comparable` objects and calls `compareTo()` in one of its methods + - this method takes in type `Comparable` + - the exact type of the object (and its specific version of `compareTo()` to call) is determined during runtime by the JVM +- early binding is when the type of an object is determined during compile time -### Liskov substitution principle and SOLID +## Liskov substitution principle and SOLID - what SOLID stands for - single responsibility principle: each class should represent one thing, each method should do only one thing, etc. - open-closed principle diff --git a/week-seven.md b/week-seven.md new file mode 100644 index 0000000..b292f40 --- /dev/null +++ b/week-seven.md @@ -0,0 +1,30 @@ +## List the common operations and properties of all lists as distinct from collections. +- lists + - ordered + - operations happen at a particular index + - grow/shrink to accommodate add/remove actions + - `List` extends `Collection` and `Iterable` +- collections + - unordered + - have size limits + - can be equal to each other even if the order of the elements is different + - `Collection` extends `Iterable` +- `ListIterator` + - extends `Iterator` + - adds `hasPrevious()`, `next/previousIndex()`, etc. + - can be initialized at specific indexes + +## autoboxing (boxing/unboxing) +- this is when Java automatically converts primitive types into their `Object`/wrapper types +- example where this would be needed: when adding an `int` to an `ArrayList` +- primitive -> object is "boxing" +- object -> primitive is "unboxing" + +## Extend the AbstractCollection implementation into AbstractList and ArrayList implementations and justify design decisions. + + +## Analyze the ArrayList implementation to determine algorithmic efficiency. + + +## Use an ArrayList data structure to solve a problem. + diff --git a/week-six.md b/week-six.md new file mode 100644 index 0000000..562b010 --- /dev/null +++ b/week-six.md @@ -0,0 +1,43 @@ +## generics +- generic types cannot be primitives + - you have to use the wrapper classes Java provides (`Integer` instead of `int`, etc.) + - this is called "boxing", putting a primitive into a value type + - unboxing is where you convert a value type into a primitive +- `Collection` + - it's an interface that extends `Iterable` + - various data structures inherit `Collection` + - its generic, so when you instantiate a collection you have to provide a type + - unlike `Lists`, collections don't guarantee order + - if you want to iterate over a collection, you have to create a class that implements `Iterator` + - _AND_ the collection class must implement `iterator()` that returns an instance of the `Iterator` class + - the requirement for `iterator()` comes from the `Iterable` interface + - you can then instantiate and use that iterator in your collection class to loop over your collections + - there should be a method in your collection class that returns a new `Iterator` / `ConcreteIteratorClassYouMade` + - if your collection class implements `Iterable` (i.e. it has a method `iterator()` that creates an `Iterator`), then you should be able to use a for-each loop on it + - `for ([whatever your collection type is] i : collection) { }` + - the iterator class can have a `remove()` method + ``` + public void remove() { + if (!nextCalled) { + throw new IllegalStateException("No prior call to next"); + } + --index; + data[index] = data[size - 1]; + data[size - 1] = null; + --size; + nextCalled = false; + } + ``` + - `nextCalled` is set to true each time `next()` is called because the element at `index` cannot be removed if it hasn't been iterated over using yet + - you wouldn't know what you're removing if you don't call `next()` first + - this design, where you have a method (`iterator()`) that returns a new object that can be called on to do a job is the **factory pattern** + - the factory class is the concrete class that creates/implements `Iterator` + +## type parameters +A type parameter is essentially a variable that holds a reference to a type instead of a value. Generic classes are classes that take in a type parameter and create an instance of the class that uses that type parameter wherever it is used in the generic class definition. Example, you can create an instance of `SomeConcereteCollection` that holds a collection of `Person` like this: `new SomeConcereteCollection()`. + +## bound type parameter +The method `binarySearch()` needs to compare the values in the array `arr` in order to perform the search, so the array that gets passed in must be a type that implements `Comparable`. The bound parameter `T extends Comparable` makes sure of this. + +## type erasure +Type erasure happens when the Java compiler replaces generic types with the concrete types implied by the parts of the code that instantiate the generic classes. By the time the JVM gets to runtime, the bytecode has no reference to generic types. Everything has been given concrete types. diff --git a/week-ten.md b/week-ten.md new file mode 100644 index 0000000..4b0c41b --- /dev/null +++ b/week-ten.md @@ -0,0 +1,28 @@ +## stacks +- stacks are LIFO structures (last in, first out) +- they're an array of elements where you can only add to the end and remove from the end +- examples of real-world stacks include a stack of chairs or plates and PEZ dispensers +- methods that stacks (should) implement + - `bool push(E data)` adds `data` to the end of the array + - `E pop()` removes and returns the last element in the array + - `E peek()` returns the last element in the array without removing it + - `bool isEmpty()` tells whether the array has any elements in it (obviously) + +## infix and postfix +- infix notation + - e.g. 3 + 7 * 2 - 8 / (6 - 2) + - it's easy for humans to perform because we jump back and forth and easily follow order of operations + - but computers don't have the same top-down view of the problem like we do +- postfix notation + - e.g. 3 7 2 * + 8 6 2 - / - + - you loop over the expression, left to right + - you add each element to a stack (3, then 7, then 2) + - when you reach an operand, you pop the last two numbers off the stack and perform the operation on them + - pop off 2 and 7 and multiply them + - then you add the result to the stack + - the stack now looks like 3, 14 + - you end up with one number on the stack, the final answer + - this is easy for a computer to calculate + - a computer simply goes through the characters/numbers one at a time + - it doesn't have to have a top-down view of the problem or jump around to figure out the order in which operations have to be done + - you can use a stack to evaluate the expression with a simple algorithm diff --git a/week-three.md b/week-three.md new file mode 100644 index 0000000..aacefd2 --- /dev/null +++ b/week-three.md @@ -0,0 +1,30 @@ +## example of interface vs. abstract +- "sortable" would be an interface because it describes the abilities/behaviors that a sortable object must have (e.g., a method called `sort()`) +- "shape" would probably be an abstract class because shapes are objects in themselves that all share certain methods AND properties (e.g., `numberOfSides`, `calculateArea()`, etc.) +- abstract classes can have properties, while interfaces can't + +## Explain what design patterns are and how they are used. +- design patterns are "common solutions to common problems" +- they're tried-and-true ways to organize classes and behaviors + +## Recognize and apply the Template Method design pattern to solve a given problem. +- you have a fixed algorithm that does different things for different types +- a method takes objects of any class that implements some interface and calls a method defined in that interface +- that method calls a different version of the interface method depending on the specific subclass/type of the object being passed in + +## Recognize and apply the Strategy design pattern to solve a given problem. +- only some animals fly, so don't put `fly()` in an `Animal` class +- also, you should try to avoid creating interfaces just to force the creation of a method/action +- a change in a superclass/interface shouldn't break the subclasses +- use strategy pattern + - create an interface `Flies` with `flies()` + - create two classes that implement `Flies`, one called `CanFly` and one called `CantFly` + - add an instance of `Fly` called `flyingType` to `Animal` + - then write a method `tryToFly()` that calls `flyingType.fly()` + - you can also add `setFlyingAbility()` to `Animal` so you can change the flying type for each animal + - all the subclasses of `Animal`, you can now set `flyingType` to an instance of whichever `Flies` subclass is appropriate +- this doesn't break old classes and allows us to add multiple types of flying (e.g., can fly, can't fly, can flap, can fly when it reaches a certain age, etc.) + +## Explain how interfaces reduce coupling while increasing code reuse. +- interfaces reduce coupling and code duplication by allowing all classes that implement the same interface to be used by the same methods +- instead of writing a different method for each class, you can write one that takes in arguments of the interface type diff --git a/week-two.md b/week-two.md index ba24924..8fbdb35 100644 --- a/week-two.md +++ b/week-two.md @@ -1,23 +1,25 @@ -### abstract classes vs interfaces +## abstract classes vs interfaces +- classes and abstract classes define what an object _is_; an interface defines what an object can _do_ - neither of these can be instantiated (you can't "new" them up) - you "extend" abstract classes, and then you can create objects from those subclasses - you "implement" interfaces, and then you can create objects from those subclasses -- classes derived from interfaces or abstract classes are called "concrete classes"; these are classes that can be instantiated (i.e. you can create objects from them) + - **but** you can assign an object that implements, say, the Measurable interface to a variable of type Measurable; you can't instantiate a Measurable, but you can use it as a variable type - abstract classes - abstract classes can have implemented methods, abstract methods and properties - - abstract methods aren't implemented (i.e., they don't have bodies) in the abstract class, but in the subclasses they _must_ be implemented + - abstract methods aren't implemented (i.e., they don't have bodies) in the abstract class, but they _must_ be implemented in the subclasses - if a subclass doesn't have a constructor, then when you create a new subclass object, Java will run the superclass' constructor - interfaces - an interface defines how we interact with the object (what the object can do) - none of the methods in an interface are implemented, the interface only lists the signatures of the methods (name, return type, parameters) - if a subclass implements an interface, it must define each method listed in the interface - there are no properties defined in an interface +- a class can `extend` only one class, but it can `implement` as many interfaces as needed - you can design a program to have an interface the then an abstract superclass that implements the interface, then subclasses that extend the abstract class - let's say we have an `interface Person`, that describes what each `Person` type _has_ to be able to do - then an abstract class (`AbstractPerson`) either implements each method from the interface _or_ marks it abstract to force the subclasses to implement them - each subclass that extends `AbstractPerson` must implement any methods marked as abstract in `AbstractPerson` -### implicit and explicit object conversion +## implicit and explicit object conversion - implicit - objects of a subclass can be used anywhere that a superclass object can be used without having to be cast into the parent type - if you have a `Student` object, it can be used anywhere a `Person` object is required (assuming `Student` extends/implements `Person`) @@ -25,7 +27,7 @@ - explicit conversion is when an object is cast into another type - a `Person` object has to be cast with `(Student)personObject` if you want to use `Student` methods on it -### overriding equals method +## overriding equals method - the default `equals()` method in the `Object` class only returns true if the objects being compared are the exact same object ``` Person x = new Person("tony"); @@ -56,19 +58,25 @@ public boolean equals(Object object) - you should check to see if the values are "close enough", since they could vary by tiny amounts - `Math.abs(oneValue - otherValue) < 1e-6` -### types of classes -- concrete: a class that can be instantiated (you can "new" it up) -- base: -- derived: -- final: -- static: -- abstract: +## types of classes +- concrete: a regular class; it can be instantiated (you can "new" it up) +- base: a parent class, a class that another class extends +- derived: a child class, a class that extends another class +- abstract: a class that has one or more abstract methods in it +- static: you can't create an object from a static class; you use a member defined in a static class with `ClassName.MethodName()/PropertyName`; +- final: final classes cannot be extended; final **methods** cannot be overridden; final **variables** can only be assigned once - (interfaces aren't classes, they're more like blueprints for classes) -### composition +## composition +- composition is when an object contains another object +- the contained object cannot exist outside of the container class +- if inheritance makes "is a" relationships, then composition makes "has a" relationships +## callback methods +![callback pattern](https://github.com/ruthrootz/java-oop-class-notes/blob/main/callback-methods.png) +- you can pass a method into another method and call the first method inside the second -### open-closed, interface segregation, and dependency inversion principles (SOLID) +## open-closed, interface segregation, and dependency inversion principles (SOLID) - open-closed - a system can be extended but should not be modified - e.g., you can add a subclass but you can't (or don't have to) change the superclass @@ -78,8 +86,9 @@ public boolean equals(Object object) - dependency inversion - high-level modules shouldn't depend on low-level modules, they shouldn't have to know what's going on in them - another way to put it, the coupling between two classes should be as low as possible, one class doesn't have to know about or bother with the implementation of another class it's using + - changing one of the classes shouldn't change how the other class (the dependent class) uses it -### cohesion and coupling +## cohesion and coupling - the goal: classes should have strong cohesion, weak coupling - cohesion: each class should do only one thing - coupling @@ -87,5 +96,5 @@ public boolean equals(Object object) - classes shouldn't depend on the details of another class, the classes should work independently - changing how one of them works shouldn't break the other -### access modifiers +## access modifiers ![access modifiers](https://github.com/ruthrootz/java-oop-class-notes/blob/main/access-modifiers.png)