Constructors

Constructors are special methods within a class that are used for initializing objects.

A constructor is typically used to set initial values for the instance variables of an object when it is created. It ensures that the object is in a valid state and ready to be used. Constructors are commonly defined with the same name as the class and do not have a return type.

python example

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def display_info(self):
        print(f"Name: {self.name}, Age: {self.age}")


# Creating an instance of the Person class using the constructor
person = Person("John Doe", 25)

# Calling the display_info method to print the person's information
person.display_info()

Java example

public class Car {
    private String brand;
    private String color;
    private int year;

    // Constructor
    public Car(String brand, String color, int year) {
        this.brand = brand;
        this.color = color;
        this.year = year;
    }

    // Getter and Setter methods
    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }
}

You can create an instance of the Car class and initialize its state using the constructor like this:

Car myCar = new Car("Toyota", "Blue", 2022);

Now you can access the object’s properties using getter methods:

String carBrand = myCar.getBrand();
String carColor = myCar.getColor();
int carYear = myCar.getYear();

Class inheritance

Class inheritance is a mechanism for using the interface and implementation of one or more classes as the basis for another class. The inheriting class, also known as a subclass, inherits from one or more classes, known as superclasses

class inheritance allows you to create a new class (the “child” class) that inherits the attributes and methods of an existing class (the “parent” class). The child class can then add new functionality or override existing behavior as needed.

python example

class Vehicle:
    def __init__(self, brand, color):
        self.brand = brand
        self.color = color

    def drive(self):
        print(f"The {self.color} {self.brand} is driving.")

class Car(Vehicle):
    def __init__(self, brand, color, num_doors):
        super().__init__(brand, color)
        self.num_doors = num_doors

    def drive(self):
        print(f"The {self.color} {self.brand} car with {self.num_doors} doors is driving.")

    def honk(self):
        print("Beep beep!")

class Motorcycle(Vehicle):
    def drive(self):
        print(f"The {self.color} {self.brand} motorcycle is driving.")

# Creating instances of the classes
car = Car("Toyota", "Blue", 4)
motorcycle = Motorcycle("Harley Davidson", "Black")

# Calling methods
car.drive()  # Output: The Blue Toyota car with 4 doors is driving.
car.honk()  # Output: Beep beep!
motorcycle.drive() 
# Output: The Black Harley Davidson motorcycle is driving.

Java example

// Superclass
public class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void eat() {
        System.out.println(name + " is eating.");
    }
}

// Subclass
public class Dog extends Animal {
    private String breed;
    
    public Dog(String name, String breed) {
        super(name); // Call superclass constructor
        this.breed = breed;
    }
    
    public void bark() {
        System.out.println(name + " is barking.");
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("Buddy", "Labrador");
        myDog.eat(); // Inherited from Animal class
        myDog.bark(); // Defined in Dog class
    }
}

In this example, the Animal class is the superclass, and the Dog class is the subclass that inherits from Animal. The Animal class has a constructor and a method called eat(). The Dog class extends Animal and adds an additional field called breed and a method called bark().

When creating an instance of the Dog class, the super(name) statement in the Dog constructor calls the superclass constructor to initialize the name field inherited from the Animal class.

In the main method, we create an instance of the Dog class called myDog. We can call both the inherited eat() method from the Animal class and the bark() method defined in the Dog class on the myDog object.

This is a basic example of class inheritance in Java. Inheritance allows you to create a hierarchy of classes with increasing specialization and code reuse. Subclasses can inherit and extend the behavior of their superclasses, adding new fields and methods or overriding existing ones as needed.

Encapsulation

Encapsulation is one of the fundamental principles of object-oriented programming (OOP) that promotes data hiding and protects the internal state of an object from direct access. It is achieved by making the internal data members private and providing public methods (getters and setters) to access and modify the data.

In Python, you can use naming conventions to indicate the visibility of attributes and methods. By convention, a single underscore prefix _ indicates that an attribute or method is intended to be private, although it does not enforce strict access control like some other programming languages.

python example

class Car:
    def __init__(self, brand, color, year):
        self._brand = brand
        self._color = color
        self._year = year

    def get_brand(self):
        return self._brand

    def set_brand(self, brand):
        self._brand = brand

    def get_color(self):
        return self._color

    def set_color(self, color):
        self._color = color

    def get_year(self):
        return self._year

    def set_year(self, year):
        self._year = year

In the above example, the Car class has private attributes _brand, _color, and _year. These attributes are conventionally considered private, and external code should not access them directly. Instead, public getter and setter methods are provided to access and modify these attributes.

The getter methods ( get_brand(), get_color(), get_year()) simply return the values of the corresponding attributes. The setter methods (set_brand(), set_color(), set_year()) allow external code to modify the attribute values.

Here’s an example of how you can use the Car class and its encapsulated attributes

my_car = Car("Toyota", "Blue", 2022)
print(my_car.get_brand())  # Output: Toyota

my_car.set_color("Red")
print(my_car.get_color())  # Output: Red

my_car.set_year(2023)
print(my_car.get_year())  # Output: 2023

In this example, the private attributes _brand, _color, and _year are accessed and modified using the public getter and setter methods, providing controlled access to the internal state of the Car object.

NB Encapsulation helps maintain the integrity of an object’s data and allows the class to change its internal implementation details without affecting the external code that uses the class.

Java example

public class BankAccount {
    private String accountNumber;
    private double balance;
    
    public BankAccount(String accountNumber) {
        this.accountNumber = accountNumber;
        this.balance = 0.0;
    }
    
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("Deposit of $" + amount + " successful. New balance: $" + balance);
        } else {
            System.out.println("Invalid deposit amount.");
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
            System.out.println("Withdrawal of $" + amount + " successful. New balance: $" + balance);
        } else {
            System.out.println("Insufficient funds or invalid withdrawal amount.");
        }
    }
    
    public double getBalance() {
        return balance;
    }
    
    public String getAccountNumber() {
        return accountNumber;
    }
}

In the above example, the BankAccount class encapsulates the account number and balance as private fields. These fields cannot be directly accessed from outside the class. The public methods deposit(), withdraw(), getBalance(), and getAccountNumber() provide controlled access to these fields.

The deposit() method allows positive amounts to be added to the account balance. The withdraw() method subtracts valid amounts from the balance, provided sufficient funds are available.

The getBalance() and getAccountNumber() methods are public accessors that allow other classes to retrieve the account balance and account number, respectively. However, direct modification of the account balance or account number is not allowed from outside the BankAccount class.

Here’s an example of using the BankAccount class:

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount("1234567890");
        
        account.deposit(1000.0);
        account.withdraw(500.0);
        
        double balance = account.getBalance();
        System.out.println("Current balance: $" + balance);
        
        String accountNumber = account.getAccountNumber();
        System.out.println("Account number: " + accountNumber);
    }
}

In this example, we create a BankAccount object and perform operations such as depositing and withdrawing funds. The getBalance() and getAccountNumber() methods are used to retrieve the account balance and account number, respectively.

Encapsulation allows the BankAccount class to control access to its internal state, ensuring that the account balance and account number are modified and accessed in a controlled manner. It provides a level of abstraction and protects the data from unauthorized modifications.

Abstraction

Abstraction in object-oriented programming (OOP) refers to the process of hiding the internal details and complexities of a class and providing a simplified interface for interacting with objects. It allows you to focus on what an object does rather than how it does it.

In Python, abstraction can be achieved using the (double underscore) modifier, also known as name mangling. By prefixing an attribute or method with, it becomes a private member, indicating that it should not be accessed directly from outside the class.

Here’s an example of abstraction in Python using the __ modifier:

python example

class Car:
    def __init__(self, brand, color):
        self.__brand = brand
        self.__color = color
    
    def start_engine(self):
        self.__ignite_engine()
        print("Engine started.")
    
    def __ignite_engine(self):
        print("Engine ignited.")


my_car = Car("Toyota", "Blue")
my_car.start_engine()

# Attempting to access private members directly
print(my_car.__brand)  # Raises an AttributeError
my_car.__ignite_engine()  # Raises an AttributeError

In the above example, the Car class has two private attributes, __brand and __color, which are initialized using the constructor (__init__ ). The start_engine method is a public method that can be accessed from outside the class. It internally calls a private method __ignite_engine to ignite the engine.

When creating an instance of the Car class, you can call the public method start_engine, which indirectly invokes the private method __ignite_engine to start the engine. However, attempting to access the private attributes __brand and __ignite_engine directly from outside the class will raise an AttributeError.

By using the __ modifier, we hide the internal implementation details of the class, allowing users of the class to interact with a simplified and controlled interface. This promotes abstraction and encapsulation, as the internal workings of the class are abstracted away from the user, who only needs to know how to use the provided public methods.

Java example

// Abstract class
abstract class Shape {
    public abstract double calculateArea();
    public abstract double calculatePerimeter();
}

// Concrete classes
class Rectangle extends Shape {
    private double length;
    private double width;
    
    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    
    public double calculateArea() {
        return length * width;
    }
    
    public double calculatePerimeter() {
        return 2 * (length + width);
    }
}

class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
}

// Interface
interface Drawable {
    void draw();
}

// Class implementing the interface
class Square implements Drawable {
    public void draw() {
        System.out.println("Drawing a square");
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle(5, 3);
        System.out.println("Rectangle area: " + rectangle.calculateArea());
        System.out.println("Rectangle perimeter: " + rectangle.calculatePerimeter());
        
        Shape circle = new Circle(2.5);
        System.out.println("Circle area: " + circle.calculateArea());
        System.out.println("Circle perimeter: " + circle.calculatePerimeter());
        
        Drawable square = new Square();
        square.draw();
    }
}

In this example, we have an abstract class called Shape that defines two abstract methods: calculateArea() and calculatePerimeter(). The abstract class cannot be instantiated directly, but it provides a common interface for its concrete subclasses.

The Rectangle and Circle classes extend the Shape abstract class and provide their own implementations of the abstract methods. They calculate the area and perimeter specific to rectangles and circles.

The Drawable interface declares a single method draw(), which is implemented by the Square class.

In the Main class, we create objects of Rectangle and Circle and call their respective methods to calculate the area and perimeter. We also create an object of Square and call its draw() method.

Abstraction allows us to work with high-level concepts such as shapes without worrying about their specific implementations. It provides a way to define common behaviors and enforce their implementation in concrete classes. Interfaces further enhance abstraction by defining contracts that classes must adhere to.

Polymorphism

Polymorphism is a fundamental concept in object-oriented programming (OOP) that allows objects of different classes to be treated as objects of a common superclass. Polymorphism enables the same method to be invoked on different objects, resulting in different behaviors depending on the actual type of the object.

python example

class Animal:
    def sound(self):
        pass

class Cat(Animal):
    def sound(self):
        return "Meow!"

class Dog(Animal):
    def sound(self):
        return "Woof!"

class Cow(Animal):
    def sound(self):
        return "Moo!"

# Usage
animals = [Cat(), Dog(), Cow()]

for animal in animals:
    print(animal.sound())

In this example, we have an Animal superclass with a sound() method defined as a placeholder using the pass statement. This method will be overridden by subclasses.

We then define three subclasses: Cat, Dog, and Cow, which inherit from the Animal superclass and implement their own sound() methods.

In the usage section, we create a list animals containing instances of the different subclasses. We iterate over the list and call the sound() method on each object. Despite calling the same method name (sound()), the actual behavior differs based on the object’s type.

Each object in the animals list invokes its respective sound() method, demonstrating polymorphism. The same method call (sound()) produces different results depending on the actual type of the object.

Polymorphism allows us to write more flexible and reusable code by treating objects of different classes in a uniform way, as long as they share a common superclass or interface.

java example

// Superclass
class Animal {
    public void makeSound() {
        System.out.println("The animal makes a sound.");
    }
}

// Subclasses
class Dog extends Animal {
    public void makeSound() {
        System.out.println("The dog barks.");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("The cat meows.");
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        
        animal1.makeSound(); // Calls the overridden method in Dog class
        animal2.makeSound(); // Calls the overridden method in Cat class
    }
}

Genera concept in java.

staric class

A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated. In other words, you cannot use the new operator to create a variable of the class type

A static method is a class method and belongs to the class itself. This means you do not need an instance in order to use a static method. A non-static method is an instance method and belongs to each object that is generated from the class.

static method

What is a Static Method in Java? A static method is a method that belongs to a class rather than an instance of a class. This means you can call a static method without creating an object of the class. Static methods are sometimes called class methods

static variable

When a variable is declared static in Java programming, it means that the variable belongs to the class itself rather than to any specific instance of the class. This means that there is only one copy of the variable in memory, regardless of how many instances of the class are created

finally Keyword

The finally keyword is used to create a block of code that follows a try block. A finally block of code always executes, whether or not an exception has occurred. Using a finally block allows you to run any cleanup-type statements that you want to execute, no matter what happens in the protected code. A finally block appears at the end of the catch blocks and has the following syntax:

coonect java app to database

// This code is for establishing connection with MySQL
// database and retrieving data
// from db Java Database connectivity

/*
*1. import --->java.sql
*2. load and register the driver ---> com.jdbc.
*3. create connection
*4. create a statement
*5. execute the query
*6. process the results
*7. close
*/

import java.io.*;
import java.sql.*;

class GFG {
    public static void main(String[] args) throws Exception
    {
        String url
            = "jdbc:mysql://localhost:3306/table_name"; // table details
        String username = "rootgfg"; // MySQL credentials
        String password = "gfg123";
        String query
            = "select *from students"; // query to be run
        Class.forName(
            "com.mysql.cj.jdbc.Driver"); // Driver name
        Connection con = DriverManager.getConnection(
            url, username, password);
        System.out.println(
            "Connection Established successfully");
        Statement st = con.createStatement();
        ResultSet rs
            = st.executeQuery(query); // Execute query
        rs.next();
        String name
            = rs.getString("name"); // Retrieve name from db

        System.out.println(name); // Print result on console
        st.close(); // close statement
        con.close(); // close connection
        System.out.println("Connection Closed....");
    }
}