[!INDEX]

  1. Calling Parent Class Method Using super ( mom - son)
  2. more practical example of super, credit card
  3. Final , Not override, pie value
  4. Static , Not override, ElectricBoard example
  5. private , Not override, family picture
  6. Pt M/T Synchronized, Acceptable
  7. Child M/T Synchronized, Acceptable
  8. Child mt() Is Strictfp, Version Dependent, java 17
  9. parent mt() is strictfp, version dependent
  10. Abs. Cls. + Abs. + Concrete Mt., no body defined, instantiate directly
  11. why Abs. cls. cannot be instantiated directly
  12. Abs. Cls. + Abs. Mt. inherit + body defined + OK
  13. Itf. mt() implemented + body not defined
  14. Itf. mt() + Abs. mt() + must defined body - OK

1 - Calling Parent Class Method Using super ( mom - son - money)

public class Mom {
    void money() {
        System.out.println("have money ");
    }
}
class Son extends Mom {
    @override
    void money() {
        super.money(); // Calls the parent class's show method
        System.out.println("need money to spend ");
    }
    public static void main(String[] args) {
        Son x = new Son();
        x.doShopping();
    }
}
have money
need money to spend

[!NOTE]

  1. This is useful for extending or modifying the behavior of inherited methods while still leveraging the functionality of the parent class's implementation.

2 - more practical example of super, credit card

// Parent class
public class Payment {
    void cc_process_start(double amount) {
        // Generic payment processing steps
        System.out.println("Processing payment of $" + amount);
        payment_slip(amount);
    }
    void payment_slip(double amount) {
        System.out.println("print slip of $" + amount);
    }
}

// Child class
class CreditCardPayment extends Payment {

    void processPayment(double amount) {
        // Specific steps for credit card processing
        check_card_pin();
        // Call the parent class's method for common processing
        super.cc_process_start(amount);
        // Additional steps specific to credit card processing
        debit_amount(amount);
    }

    void check_card_pin() {
        System.out.println("pin in correct, please proceed");
    }
    void debit_amount(double amount) {
        System.out.println("debit amount is $" + amount);
    }
    public static void main(String[] args) {
        CreditCardPayment rajat = new CreditCardPayment();
        rajat.cc_process_start(100.0);
    }
}

[!NOTE]

  1. This example demonstrates how the super keyword allows the CreditCardPayment class to leverage the generic payment processing steps defined in the Payment class while adding its own specific behavior for handling credit card payments. This is useful for code reuse and maintaining a clean and organized codebase.

3 - Final mt , Not override, pie value

public class Pie {
    final void pieValue() {
        System.out.println("pie value is 3.14");
    }
}
class Math extends Pie {
    void pieValue() { // Compilation error: Cannot override the final method from G21
        System.out.println("pie value is 3.00 ");
    }

    public static void main(String[] args) {        
        Math x = new Math();
        x.pieValue();
    }
}

[!NOTE]

  1. final methods are designed to prevent further modification to ensure consistency and prevent changes that could break the expected behavior.

4 - Static , Not override, ElectricBoard example

public class ElectricBoard {
    static void voltage() {
        System.out.println("static-1");
    }
}
class Electric extends ElectricBoard {
    void voltage() { 
        System.out.println("static-2");
    }
    // ------code 2
    // static void show() { // This is method hiding, not overriding
    //     System.out.println("static-2");
    // }
    public static void main(String[] args) {        
        ElectricBoard.voltage(); // Calls G22's show method
        Electric.voltage(); // Calls Xyz's show method
    }
}

[!NOTE]

  1. static methods belong to the class, not instances, so they follow a different resolution mechanism.

5 - private , Not override, family picture

public class FamilyPicture {
    private void pics() { // This method is private to G23, only accesible in own class
        System.out.println("private-1");
    }
}
class Outsider extends FamilyPicture {
    void pics() { // This method is a new method in Xyz
        System.out.println("private-2");
    }
    public static void main(String[] args) {        
        Outsider x = new Outsider();
        x.pics(); // Calls Xyz's show method
    }
}

[!NOTE]

  1. In the provided code, the private method in the parent class G23 is not visible to the subclass Xyz. Instead, Xyz defines its own show method, which is independent of the show method in G23.

6 - Pt M/T Synchronized, Acceptable

public class G24 {
    synchronized void show() { 
        System.out.println("synchronized-1");
    }
}
class Xyz extends G24 {
    void show() {
        System.out.println("synchronized-2");
    }
    public static void main(String[] args) {        
        Xyz x = new Xyz();
        x.show();
    }
}

[!NOTE]

  1. The synchronized keyword in the parent class is effectively "hidden" by the non-synchronized method in the subclass.

7 - Child M/T Synchronized, Acceptable

public class G26 {
    void show() { 
        System.out.println("synchronized-1");
    }
}
class Xyz extends G26 {
    synchronized void show() { 
        System.out.println("synchronized-2");
    }
    public static void main(String[] args) {  
        G26 g1 = new G26();
        g1.show();      
        Xyz x = new Xyz();
        x.show();
    }
}

[!NOTE]

  1. The show method in Xyz is synchronized. This means that if multiple threads were accessing this method, only one thread could execute it at a time.

8 - Child mt() Is Strictfp, Version Dependent, java 17

public class G27 {
    void show() { 
        System.out.println("strictfp-1");
    }
}
class Xyz extends G27 {
    strictfp void show() { 
        System.out.println("strictfp-2");
    }   
    public static void main(String[] args) {  
        G27 g1 = new G27();
        g1.show();      
        Xyz x = new Xyz();
        x.show();
    }
}

[!NOTE]

  1. The strictfp keyword affects ==floating-point calculations== but does not change the method's ==functionality== or output directly.
  2. It’s important to note that the strictfp keyword in the subclass Xyz does not affect the show method in the parent class G27.
  3. When you call g1.show(), it uses the show method from G27, and when you call x.show(), it uses the show method from Xyz.
  4. Starting with Java 17, the strictfp keyword is no longer necessary for ensuring strict floating-point behavior. This is because, from Java 17 onwards, ==all floating-point expressions are evaluated strictly according to the IEEE 754 standard by default.==
  5. This change simplifies code and eliminates the need to explicitly mark methods or classes with strictfp for floating-point precision, as the default behavior now covers these requirements.

9 - parent mt() is strictfp, version dependent

public class G28 {
    strictfp void show() { 
        System.out.println("strictfp-1");
    }
}
class Xyz extends G28 {
    void show() { 
        System.out.println("strictfp-2");
    }
    public static void main(String[] args) {  
        G28 g1 = new G28();
        g1.show();      
        Xyz x = new Xyz();
        x.show();
    }
}

[!NOTE]

  1. The subclass Xyz overrides the show method without the strictfp keyword, and this is acceptable.

10 - Abs. Cls. + Abs. + Concrete Mt., no body defined, instantiate directly

abstract public class G16 {
    abstract void display(); // Abstract method, must be implemented by subclasses
    void show() {
        System.out.println("parent exception to child exception-1");
    }
}
class Xyz extends G16 {
    @Override
    void show() {
        System.out.println("parent exception to child exception -2");
    }
    public static void main(String[] args) {
        G16 t = new G16(); // compile-time error because G16 is abstract
        Xyz x = new Xyz();
        x.show(); // Output: parent exception to child exception -2
        x.display(); // Output: Implementing display method in Xyz
    }
}

[!NOTE]

  1. Abstract classes cannot be instantiated directly, so the line G16 t = new G16(); will cause a compile-time error. The Xyz class extends G16 and provides implementations for the display() and show() methods.

11 - why Abs. cls. cannot be instantiated directly

[!NOTE]

  1. Incomplete Implementation

Abstract classes are meant to serve as base classes with some level of incomplete implementation. They often contain abstract methods, which ==are declared but not implemented==. These methods must be implemented by ==concrete subclasses==. Since an abstract class may have one or more methods without any implementation, creating an instance of such a class would be meaningless and lead to incomplete objects.

  1. Encapsulation of Common Behavior

Abstract classes are designed to encapsulate ==common behavior== and provide a ==common interface== for its subclasses. They allow you to define methods that can be shared among multiple subclasses, while ==forcing== those subclasses to ==provide specific implementations== for abstract methods. By preventing instantiation of abstract classes, Java ensures that only fully defined objects are created.

  1. Enforcing Design Contracts

Abstract classes help enforce design contracts in your code. By requiring subclasses to implement abstract methods, abstract classes ensure that certain behaviors are provided by all subclasses. This promotes consistency and reliability in the design of software systems.

  1. Polymorphism

Abstract classes enable polymorphism by allowing you to define a common interface for a group of related classes. You can create methods that operate on references to the abstract class, allowing you to write more flexible and reusable code. By ensuring that abstract classes cannot be instantiated, Java maintains the integrity of polymorphism and ensures that only concrete subclasses are used.

  1. Avoiding Incomplete Objects

If abstract classes could be instantiated, it would be possible to create objects that do not have complete implementations, leading to potential runtime errors and undefined behavior. By prohibiting the instantiation of abstract classes, Java ensures that all objects created are fully defined and functional.


12 - Abs. Cls. + Abs. Mt. inherit + body defined + OK

abstract public class G17 {
    // Abstract method, must be overridden by subclasses
    abstract void display();
}
class Xyz extends G17 {
    @Override
    void display() {
        System.out.println("Implemented display method in Xyz");
    }
    public static void main(String[] args) {
        Xyz x = new Xyz();
        x.show();     // Output: abstract class abstract m/t must oR -2
        x.display();  // Output: Implemented display method in Xyz
    }
}

13 - Itf. mt() implemented + body not defined

interface i1 {
    void display(); // By default, all methods in an interface are abstract
}
abstract public class G18 {
    void show() {
        System.out.println("abstract class abstract m/t must oR -1");
    }
}
class Xyz extends G18 implements i1 {
    // Overriding the concrete method from G18
    void show() {
        System.out.println("abstract class, abstract m/t must oR -2");
    }
    public static void main(String[] args) {
        Xyz x = new Xyz();
        x.show();       // Output: abstract class, abstract m/t must oR -2
        x.display();    // Output: Implemented display method from G18
    }
}

[!NOTE]

  1. above not allowed xyz must defined the display method body ,The type Xyz must implement the inherited abstract method i1.display()Java(67109264)

14 - Itf. mt() + Abs. mt() + must defined body - OK

interface i1 {
    void displayi1(); // By default, all methods in an interface are abstract and public
}
abstract public class G19 {
    abstract void display();
    void show() {
        System.out.println("abstract class abstract m/t must oR -1");
    }
}
class Xyz extends G19 implements i1 {
    // Implementing the abstract method from G19
    void display() {
        System.out.println("Implemented display method from G19");
    }
    // Implementing the abstract method from i1
    public void displayi1() {
        System.out.println("Implemented display method from i1");
    }
    // Overriding the concrete method from G19
    void show() {
        System.out.println("interface m/t -2");
    }
    public static void main(String[] args) {
        Xyz x = new Xyz();
        x.show();       // Output: interface m/t -2
        x.display();    // Output: Implemented display method from G19
        x.displayi1();  // Output: Implemented display method from i1
    }
}

[!NOTE]

  1. It highlights the importance of access modifiers, especially when implementing interface methods.