Basics of Java 3 (OOP)

Sungju Kim·2024년 7월 26일

Sparta_Coding_Camp_TIL

목록 보기
5/53

Object Oriented Programing (OOP)

Class

A class consists of fields and methods. Fields are the class object's characteristics and methods are its function/skills.

public class Car {
    String company; 
    String model;
    String color;
    double price;
    double speed;
    char gear;
    boolean lights;

    public Car() {} // default constructor

    double gasPedal(double kmh) {
        speed = kmh;
        return speed;
    }

    double brakePedal() {
        speed = 0;
        return speed;
    }

    char changeGear(char type) {
        gear = type;
        return gear;
    }

    boolean onOffLights() {
        lights = !lights;
        return lights;
    }

    void horn() {
        System.out.println("빵빵");
    }

}

It is possible to modify and access the fileds of the class when they are not declared to be public. When it is not specified private or public, the default is public. Note that here the color of the car can be set to red and called by the print function.

car1.color = "red";
System.out.println(car1.color); // output: red

Constructor

Every class needs a constructor but if a constructor does not do anything, its called a default constructor and simply no declration of a constructor is needed.

Function parameters: arbitrary aruguments

Arbitrary aruguments means that the number of parameter that will be passed in the function is undefined.

void carSpeeds(double ... speeds) {
    for (double v : speeds) {
        System.out.println("v = " + v);
    }
}

Method Overloadig vs. Method Overriding

링크텍스트

Method Orverloading (compile time polymorphism)

  • occurs within the class.
  • methods must have the same name but different parameters.
  • the return type can or can not be the same
// Java Program to Implement
// Method Overloading
import java.io.*;

class MethodOverloadingEx {

    static int add(int a, int b) { return a + b; }

    static int add(int a, int b, int c)
    {
        return a + b + c;
    }

    // Main Function
    public static void main(String args[])
    {
        System.out.println("add() with 2 parameters");
        // Calling function with 2 parameters
        System.out.println(add(4, 6));

        System.out.println("add() with 3 parameters");
        // Calling function with 3 Parameters
        System.out.println(add(4, 6, 7));
    }
}

Method Overriding (run-time polymorphism)

  • occurs between more than 2 classe in the form of inheritance.
  • methods must have the same name and same parameters.
  • the return type must be the same or co-variant (a subtype aka a more specific type of the return type declared in the superclass method, so for example instead of returning the animal, you can return the dog object in the overwritten class method which is the child object of the Animal).
  • the key word 'extends' indicated the parent/super class.
public class Main {
    // Base Class
    static class Animal 
    {
        void eat() {
            System.out.println("Animal is eating.");
        }
    }

    // Derived Class
    static class Dog extends Animal 
    {
        void eat() 
        {
            System.out.println("Dog is eating.");
        }

        // Method to call the base class method
        void eatAsAnimal() 
        {
            super.eat();
        }
    }

    public static void main(String[] args) 
    {

        Dog d1 = new Dog();
        Animal a1 = new Animal();

        // Calls the eat() method of Dog class
        d1.eat();
        // Calls the eat() method of Animal class
        a1.eat();

        // Polymorphism: Animal reference pointing to Dog object
        Animal animal = new Dog();

        // Calls the eat() method of Dog class
        animal.eat();

        // To call the base class method, you need to use a Dog reference
        ((Dog) animal).eatAsAnimal();
    }
}

Output

Dog is eating.
Animal is eating.
Dog is eating.
Animal is eating.

Static Functions

When an attribute of a class is set to static, you can access and modify it direclty via calling its class.

static String company;
public class Main {
    public static void main(String[] args) {

        Car.company = "hello world";
        System.out.println(Car.company);

        Car myCar = new Car();
        System.out.println(myCar.company);
        
        myCar.company = "good bye world";
        System.out.println(myCar.company);

    }
}

Output

hello world
hello world
good bye world

Note that after setting the Car class's company to 'hello world', the company name of the newly created Car objects also have the default comapny name of 'hello world'. This, however, can be modified.

💡 The concept of a static variable/function is similar to that of a global variable and a non-static variable/function is similar to that of a local variable.💡

this & this()

'this' key word is used when you need refer to current class you are writing your code in. Then, it is a general convention to use this.attribute_name naming. Below is an example of the Car class having multiple constructors via method overloading.

public Car(String model) {
    this.model = model;
    this.color = "Blue";
    this.price = 50000000;
}

public Car(String model, String color) {
    this.model = model;
    this.color = color;
    this.price = 50000000;
}

public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}

You can notice that there are repetitive lines due to the similarities between the three constructors. 'this()' can come in handy to simplify the code. We based the 'this()' function based on the constructors with the most number of parameters (which is inclusive of the other two).

public Car(String model) {
    this(model, "Blue", 5000);
}

public Car(String model, String color) {
    this(model, color, 5000);
}

public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}

We can see that for the parameters of 'this()' in the very first constructor is given as variable and values. The parameter of the first constructor ('model') is given as the variable and the others are given as values. Same happens for the second constructor.

💡In the second constructor the attributes of color and price will be set to "Blue" and 5000. Applies similarly for the first constructor. 💡

⚠️ Note that when using this() in a method, it must be the very execution of the method ⚠️
⚠️ Writing the code like below will give you an error! ⚠️

public Car(String model) {
    System.out.println("model = " + model);
    this(model, "Blue", 50000000);
}

Access Modified (4 types)

Public (most accessible)

  • the member (its attributes/field and its methods) is accessible from any other class.

Protected

  • the member is accessible within its own package and by child class/subclasses.
public class Example {
    protected String protectField = "I am protected";

    protected void protectedMethod() {
        System.out.println("Protected method can be accessed within the same package and by subclasses.");
    }
}

class Subclass extends Example {
    public void accessProtected() {
        System.out.println(protectedField); // attribute is accessible
        protectedMethod(); // method is accessible
    }
}


public class Main {
    public static void main(String[] args) {
        Subclass subclass = new Subclass();
        subclass.accessProtected(); // Accessible through subclass
    }
}

Default (no modifier)

  • the member is accessibile only within its own package.
  • it's used when you want the member to be package-private

💡 package = folder = directory 💡

Private (least accessible)

  • member is accessible only within its own class.

Accessing Packages (address & imports)

Car class from pk1 package is imported and another Car class from pk2 package is called by its directory address. For importing you cannot import both Car classes because they have the same name but you can both call them by addressig.

package oop.main;

import oop.pk1.Car;

public class Main {
    public static void main(String[] args) {
        Car car = new Car(); // import
        car.horn(); // pk1 

        oop.pk2.Car car2 = new oop.pk2.Car(); // address
        car2.horn(); // pk2 
    }
}

super & super()

'super' used to call fields and methods from the super/parent class in the child class.

super

public void setCarInfo(String model, String color, double price) {
    super.model = model; // sets the parent class' model
    super.color = color; // sets the parent class' color
    this.price = price; // sets the child class' model
}

super()

Child class constructor below uses the 'super(...)' to initialize its fileds.

public SportsCar(String model, String color, double price, String engine) {
    super(model, color, price);
    this.engine = engine;
}

The above code is identical to the following but just better for encapstulation and code maintainability:

public SportsCar(String model, String color, double price, String engine) {
    this.model = model;
    this.color = color;
    this.price = price;
    this.engine = engine;
}

Type Promotion & Type Casting (feat. Class)

Type Promotion (Up-casting)

Given that Mammal is the parent and Whale is the child class, in the code below, the we see that the object is called by the Whale constructor but its data type is a Mammal. The given syntax automatically converts the object to a Mammal type.

Mammal m1 = new Whale();
m1.feeding(); // output: "whale is eating!"
  • through m1, we can call methods from the Whale class that have been overwritten.
  • but cannot call methods that are in the Whale class that were not inherited from the Mammal class.

Type Casting (Down-casting)

  • You can convert back the type promotion that happened above via type casting
Whale whale = (Whale) mammal;
whale.swimming();

Abstract Class

An abstract class is a class that cannot be instantiated on its own and may contain abstract methods, which are methods declared without an implementation that must be defined by subclasses. Note that abstract methods do not have '{}' that contains the body of the methods/functions.

// here is an abstract class
public abstract class Car {
    String company;
    String color;
    double speed;  

    public double gasPedal(double kmh) {
        speed = kmh;
        return speed;
    }

    public double brakePedal() {
        speed = 0;
        return speed;
    }
	
    // this is an abstract method
    public abstract void horn();
}

When other subclasses use the abstract class, it is written like below:

public class GenesisCar extends Car {

    @Override
    public void horn() {
        System.out.println("Zenesis 빵빵");
    }
}

The key word 'extend' is used to represent the relationship between the two classes. The subclass is instantiated in the Main as below:

public class Main {
    public static void main(String[] args) {
        Car myCar = new GenesisCar();
        myCar.horn();
    }
}

Interface

Basic Syntax

  • All fields/attributes in the interface should have the data type public static final.
  • All methods need to be public abstract.
  • As shown in the example below, if you miss out on some of the rule, the compiler will fix them according to the rule!
public interface myInterface { 
	public static final char A = 'A';
    static char B = 'B';
    final char C = 'C';
    char D = 'D';

    void turnOnLight (); // public abstract void turnOnLight();
}

Implementing The Interfaces

Key word 'implements' is used when classes use interfaces. Inheretence between interfaces are called with the key word 'extends'.

💡Note that interfaces can inherite from more than one interface! 💡

// the Main class is inheriting from class D and implementing  interface C. 
public class Main extends D implements C {

    @Override
    public void a() {
        System.out.println("A");
    }

    @Override
    public void b() {
        System.out.println("B");
    }

    @Override
    void d() {
        super.d(); // get the d() from the superclass D
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.a();
        main.b();
        main.d();
    }
}

interface A {
    void a();
}

interface B {
    void b();
}

// C is inheriting from A and B
interface C extends A, B {
}

class D {
    void d() {
        System.out.println("D");
    }
}

Default & Static Method

Default Methods

  • Default methods must have a function body unlike abstract methods.

  • Default method must also be public, but will be set to public even if not stated so no need to write it.

    When does the default method come in handy

    💡 Default functions come in very handy when used in interfaces because when a class implements an interface, it needs to override all the methods in the interface.

    💡This can be very time consuming if you wanted add a new method to 5 out of the 20 classes that have implemented the interface because now you would have to write an overriding method for the 15 classes that do not need this new method.

    💡 If you make a default method you can not only use the newly created default method from the interface in those 5 classes but also override them as needed.

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }


    public static void main(String[] args) {
        Main main = new Main();
        main.a();

        // default method is called!
        main.aa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
}

Static Methods

Static methods are allowed to be called without instantiating the object. Notice that aaa() is called by simply refering to interface A.

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.a();
        main.aa();
        System.out.println();

        // static method aaa() is called.
        A.aaa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
    static void aaa() {
        System.out.println("static method");
    }
}

Interface Polymorphism

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat implements Animal {
    public void makeSound() {
        System.out.println("Cat meows");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog(); // Polymorphism
        Animal myCat = new Cat(); // Polymorphism

        myDog.makeSound(); // Outputs: Dog barks
        myCat.makeSound(); // Outputs: Cat meows
    }
}
profile
Fully ✨committed✨ developer, always eager to learn!

0개의 댓글