From 6abe0f5dc2a0ccd317b5b2fd917c0c124e7080e0 Mon Sep 17 00:00:00 2001 From: 100yo Date: Sat, 19 Oct 2024 01:02:00 +0300 Subject: [PATCH] Add Java OOP (part I) code snippets --- 02-oop-in-java-i/snippets/README.md | 1 + .../fmi/mjt/adorable/AbstractCoolPerson.java | 7 +++ .../sofia/uni/fmi/mjt/adorable/Adorable.java | 8 +++ .../uni/fmi/mjt/adorable/CoolPerson.java | 17 ++++++ .../sofia/uni/fmi/mjt/adorable/Likeable.java | 7 +++ .../sofia/uni/fmi/mjt/adorable/Lovable.java | 7 +++ .../mjt/instanceoff/InstanceOfExample.java | 59 +++++++++++++++++++ .../lockable/DefaultInterfaceExamples.java | 29 +++++++++ .../bg/sofia/uni/fmi/mjt/lockable/Door.java | 15 +++++ .../sofia/uni/fmi/mjt/lockable/Lockable.java | 21 +++++++ .../uni/fmi/mjt/lockable/OldLockable.java | 9 +++ .../bg/sofia/uni/fmi/mjt/lockable/Safe.java | 17 ++++++ .../sofia/uni/fmi/mjt/overridings/Audi.java | 5 ++ .../uni/fmi/mjt/overridings/AudiGarage.java | 23 ++++++++ .../bg/sofia/uni/fmi/mjt/overridings/Car.java | 5 ++ .../sofia/uni/fmi/mjt/overridings/Garage.java | 22 +++++++ .../fmi/mjt/statics/MethodHidingExample.java | 41 +++++++++++++ .../bg/sofia/uni/fmi/mjt/statics/Project.java | 40 +++++++++++++ .../uni/fmi/mjt/suuper/SuperExample.java | 40 +++++++++++++ 19 files changed, 373 insertions(+) create mode 100644 02-oop-in-java-i/snippets/README.md create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/AbstractCoolPerson.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Adorable.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/CoolPerson.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Likeable.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Lovable.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/instanceoff/InstanceOfExample.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/DefaultInterfaceExamples.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Door.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Lockable.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/OldLockable.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Safe.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Audi.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/AudiGarage.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Car.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Garage.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/MethodHidingExample.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/Project.java create mode 100644 02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/suuper/SuperExample.java diff --git a/02-oop-in-java-i/snippets/README.md b/02-oop-in-java-i/snippets/README.md new file mode 100644 index 00000000..0c2523b1 --- /dev/null +++ b/02-oop-in-java-i/snippets/README.md @@ -0,0 +1 @@ +# OOP in Java (part I) / Code snippets diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/AbstractCoolPerson.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/AbstractCoolPerson.java new file mode 100644 index 00000000..5ebc1562 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/AbstractCoolPerson.java @@ -0,0 +1,7 @@ +package bg.sofia.uni.fmi.mjt.adorable; + +public abstract class AbstractCoolPerson implements Adorable { + + // We are not required to implement the methods in an abstract class. + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Adorable.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Adorable.java new file mode 100644 index 00000000..ebdf50c8 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Adorable.java @@ -0,0 +1,8 @@ +package bg.sofia.uni.fmi.mjt.adorable; + +interface Adorable extends Likeable, Lovable { + + // This interface inherits both like() and love() methods and does not define new methods. + // Any class that will implement it, is required to implement both like() and love(), or declare itself as abstract. + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/CoolPerson.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/CoolPerson.java new file mode 100644 index 00000000..3c97757d --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/CoolPerson.java @@ -0,0 +1,17 @@ +package bg.sofia.uni.fmi.mjt.adorable; + +public class CoolPerson implements Adorable { + // If we do not implement all Adorable methods, we will get a compile-time error: + // "CoolPerson is not abstract and does not override abstract method like() in Likeable" + + @Override + public void like() { + System.out.println("I am liked!"); + } + + @Override + public void love() { + System.out.println("I am loved!"); + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Likeable.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Likeable.java new file mode 100644 index 00000000..7c65d25d --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Likeable.java @@ -0,0 +1,7 @@ +package bg.sofia.uni.fmi.mjt.adorable; + +interface Likeable { + + void like(); + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Lovable.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Lovable.java new file mode 100644 index 00000000..0217cb0b --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/adorable/Lovable.java @@ -0,0 +1,7 @@ +package bg.sofia.uni.fmi.mjt.adorable; + +interface Lovable { + + void love(); + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/instanceoff/InstanceOfExample.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/instanceoff/InstanceOfExample.java new file mode 100644 index 00000000..f08229c5 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/instanceoff/InstanceOfExample.java @@ -0,0 +1,59 @@ +package bg.sofia.uni.fmi.mjt.instanceoff; + +class Shape { + void draw() { + System.out.println("Drawing a shape"); + } +} + +class Circle extends Shape { + @Override + void draw() { + System.out.println("Drawing a circle"); + } +} + +class Rectangle extends Shape { + @Override + void draw() { + System.out.println("Drawing a rectangle"); + } +} + +public class InstanceOfExample { + + public static void main(String[] args) { + Shape[] shapes = new Shape[]{ + new Circle(), + new Rectangle(), + new Circle(), + new Rectangle(), + }; + + // old-school way: + for (Shape shape : shapes) { + if (shape instanceof Circle) { + System.out.println("Circle detected:"); + Circle circle = (Circle) shape; // Cast to Circle + circle.draw(); + } else if (shape instanceof Rectangle) { + System.out.println("Rectangle detected:"); + Rectangle rectangle = (Rectangle) shape; // Cast to Rectangle + rectangle.draw(); + } else { + System.out.println("Unknown shape detected."); + shape.draw(); + } + } + + // equivalent with enhanced switch + for (Shape shape : shapes) { + switch (shape) { + case Circle c -> c.draw(); + case Rectangle r -> r.draw(); + default -> System.out.println("Unexpected value: " + shape); + } + } + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/DefaultInterfaceExamples.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/DefaultInterfaceExamples.java new file mode 100644 index 00000000..264148be --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/DefaultInterfaceExamples.java @@ -0,0 +1,29 @@ +package bg.sofia.uni.fmi.mjt.lockable; + +public class DefaultInterfaceExamples { + + public static void main(String... args) { + + Door door = new Door(); + Lockable anotherDoor = new Door(); + Lockable safe = new Safe(); + anotherDoor.lock(); // Door locked. + System.out.println(safe.isLocked()); // false + System.out.println(door.isLocked()); // true + + Object obj = new Safe(); + Lockable lockable = Lockable.getInstance(true); + + // classic instanceof: explicit cast is needed in the if body + if (obj instanceof Lockable) { + ((Lockable) obj).lock(); // Safe locked. + } + + // New in Java 17: pattern matching for instanceof + if (lockable instanceof Door d) { + d.lock(); // Door locked. + } + + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Door.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Door.java new file mode 100644 index 00000000..a8e93f44 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Door.java @@ -0,0 +1,15 @@ +package bg.sofia.uni.fmi.mjt.lockable; + +public class Door implements Lockable, OldLockable { + + @Override + public void lock() { + System.out.println("Door locked."); + } + + @Override + public boolean isLocked() { + return true; + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Lockable.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Lockable.java new file mode 100644 index 00000000..83d538cb --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Lockable.java @@ -0,0 +1,21 @@ +package bg.sofia.uni.fmi.mjt.lockable; + +public interface Lockable { + + void lock(); + + default boolean isLocked() { + return false; + } + + // Static factory method: typical use of static methods in interfaces. + // Keep calm - will learn what Factory is in the Design Patterns lecture + static Lockable getInstance(boolean isDoor) { + if (isDoor) { + return new Door(); + } else { + return new Safe(); + } + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/OldLockable.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/OldLockable.java new file mode 100644 index 00000000..c1537330 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/OldLockable.java @@ -0,0 +1,9 @@ +package bg.sofia.uni.fmi.mjt.lockable; + +public interface OldLockable { + + default boolean isLocked() { + return true; + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Safe.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Safe.java new file mode 100644 index 00000000..98df8b2e --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/lockable/Safe.java @@ -0,0 +1,17 @@ +package bg.sofia.uni.fmi.mjt.lockable; + +public class Safe implements Lockable, OldLockable { + + @Override + public void lock() { + System.out.println("Safe locked."); + } + + @Override + public boolean isLocked() { + // We will get a compile-time error, if we don't override the isLocked() method here: + // - "Safe inherits unrelated defaults for isLocked() from types Lockable and OldLockable" + return Lockable.super.isLocked(); + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Audi.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Audi.java new file mode 100644 index 00000000..44cb7b1c --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Audi.java @@ -0,0 +1,5 @@ +package bg.sofia.uni.fmi.mjt.overridings; + +public class Audi extends Car { + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/AudiGarage.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/AudiGarage.java new file mode 100644 index 00000000..2106c824 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/AudiGarage.java @@ -0,0 +1,23 @@ +package bg.sofia.uni.fmi.mjt.overridings; + +public class AudiGarage extends Garage { + + public AudiGarage() { + // Note that parent default constructor will be invoked prior to this one. + // Calling it explicitly with super() here will have the same effect + System.out.println("Audi garage constructed"); + } + + public static void main(String... args) { // varargs syntax + new AudiGarage(); + } + + @Override + public Audi repair(Car c) { + // 1. access modifier upgraded from protected to public. Trying to reduce it to private will not compile + // 2. covariant return type: overriden method in parent returns Car + // 3. signature remains identical: otherwise, with the @Override annotation in place, will not compile + return new Audi(); + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Car.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Car.java new file mode 100644 index 00000000..f9ad8be6 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Car.java @@ -0,0 +1,5 @@ +package bg.sofia.uni.fmi.mjt.overridings; + +public class Car { + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Garage.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Garage.java new file mode 100644 index 00000000..42d98a26 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/overridings/Garage.java @@ -0,0 +1,22 @@ +package bg.sofia.uni.fmi.mjt.overridings; + +public class Garage { + + public Garage() { + System.out.println("Garage constructed"); + } + + protected Car repair(Car c) { + return new Car(); + } + + public Car repair(Car c, String customerName) { + // overloaded method: + // 1. access modifier may be any + // 2. return type may be any + // 3. name should be identical + // 4. parameter list should be different + return this.repair(c); // "this." is optional here + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/MethodHidingExample.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/MethodHidingExample.java new file mode 100644 index 00000000..a2a16041 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/MethodHidingExample.java @@ -0,0 +1,41 @@ +package bg.sofia.uni.fmi.mjt.statics; + +class Parent { + void display() { + System.out.println("Non-static method in Parent"); + } + + static void staticDisplay() { + System.out.println("Static method in Parent"); + } +} + +class Child extends Parent { + @Override + void display() { + System.out.println("Non-static method in Child"); + } + + static void staticDisplay() { + System.out.println("Static method in Child (Hidden)"); + } +} + +public class MethodHidingExample { + public static void main(String[] args) { + Parent parent = new Parent(); + Parent childAsParent = new Child(); + Child child = new Child(); + + parent.display(); // Output: Non-static method in Parent + childAsParent.display(); // Output: Non-static method in Child + + parent.staticDisplay(); // Output: Static method in Parent; same as calling Parent.staticDisplay(); + childAsParent.staticDisplay(); // Output: Static method in Parent, because the reference type is Parent; same as calling Parent.staticDisplay(); + child.staticDisplay(); // Output: Static method in Child (Hidden), because the reference type is Child;same as calling Child.staticDisplay(); + + // In summary - static methods belong to the class and no overriding is possible - + // it's possible to redefine the same method in the child class, but that's not overriding. + } +} + diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/Project.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/Project.java new file mode 100644 index 00000000..ea2759e6 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/statics/Project.java @@ -0,0 +1,40 @@ +package bg.sofia.uni.fmi.mjt.statics; + +public class Project { + + private static final String PROJECT_PREFIX = "proj-"; // constant + private static int totalProjectInstances; + + private String name; + + public Project() { + // We can use static variable to count the number of Project instances created. + // All instances of Project will share the same copy of the variable. + + name = PROJECT_PREFIX + totalProjectInstances++; + } + + public String getName() { + return name; + } + + public static int getTotalProjectInstances() { + return totalProjectInstances; + } + + // We cannot use instance variables/methods in static methods because + // static methods are not bound to any instance, but rather to the class itself + // Uncommenting the method below will not compile: + // "non-static variable name cannot be referenced from a static context" + + //public static void printName() { + // System.out.println(name); + //} + + public static void main(String... s) { + System.out.println(new Project().getName()); + System.out.println(new Project().getName()); + System.out.println(new Project().getName()); + } + +} diff --git a/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/suuper/SuperExample.java b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/suuper/SuperExample.java new file mode 100644 index 00000000..74035913 --- /dev/null +++ b/02-oop-in-java-i/snippets/src/bg/sofia/uni/fmi/mjt/suuper/SuperExample.java @@ -0,0 +1,40 @@ +package bg.sofia.uni.fmi.mjt.suuper; + +class Parent { + int parentValue; + + Parent(int parentValue) { + this.parentValue = parentValue; + } + + void displayParent() { + System.out.println("Parent value: " + parentValue); + } +} + +class Child extends Parent { + int childValue; + + Child(int parentValue, int childValue) { + super(parentValue); // Call the superclass constructor + this.childValue = childValue; + } + + void displayChild() { + System.out.println("Child value: " + childValue); + } + + void displayParentAndChild() { + super.displayParent(); // Call the parent class method using super + displayChild(); + } +} + +public class SuperExample { + public static void main(String[] args) { + Child child = new Child(10, 20); + + child.displayParentAndChild(); + } +} +