# Notes

The Four CornerStones of OOP!
OOP 的四个基石!

  • Abstraction (vs. Interfaces)
    抽象(与接口)
  • Polymorphism (many shapes and forms)
    多态性(许多形状和形式)
  • Inheritance (Type/subtype)
    继承(类型 / 子类型)
  • Encapsulation (data hiding)
    封装(数据隐藏)

# Abstraction 抽象

A class that is declared using abstract keyword is known as abstract class.
使用 abstract 关键字声明的类称为抽象类。

It can have abstract methods (methods without body) as well as concrete methods (regular methods with body).
它可以有抽象方法(没有主体的方法)以及具体方法(有主体的常规方法)。

# Rules

An abstract class can not be instantiated, which means you are not allowed to create an object of it.
抽象类无法实例化,这意味着不允许您创建抽象类的对象。

A class derived from the abstract class must implement all those methods that are declared as abstract in the parent class.
从抽象类派生的类必须实现在父类中声明为抽象的所有那些方法。

# Why use an abstract class?

Consider class Animal .
It may have a method makeSound() and subclasses of it like Dog , Cat , Lion , etc.
Since the animal sounds differ from one animal to another, there is no point to implement this method in parent class.
This is because every child class must override this method to give its own implementation details.
Ex. Dog class will say will say Woof and Cat class will say Meow .

So when we know that all the animal child classes will and should override this method, then there is no point to implement this method in parent class.
因此,当我们知道所有动物子类都将并且应该重写此方法时,则没有必要在父类中实现此方法。

Thus, making this method abstract would be the good choice as by making this method abstract we force all the sub classes to implement this method ( otherwise you will get compilation error).
因此,使此方法为 “抽象” 将是一个不错的选择,因为通过使该方法成为抽象,我们将强制所有子类实现该方法(否则,您将获得编译错误)。

Also we need not to give any implementation to this method in parent class.
同样,我们不需要在父类中对该方法进行任何实现。

Code sample
//abstract (parent) class
abstract class Animal{
	//abstract method
	public abstract void makeSound();
}
//Dog class (extends) Animal class
public class Dog extends Animal{
	public void makeSound(){
		System.out.println("Woof");
	}
	public static void main(String args[]){
		Animal obj = new Dog();
		obj.makeSound();
	}
}

# Interfaces 接口

Interface looks like a class but it is not a class.
接口看起来像一个类,但不是一个类。

An interface can have methods and variables.
接口可以具有方法和变量。

Methods declared in interface are by default abstract (only method signature, no body).
在接口中声明的方法,默认情况下是抽象的(仅方法签名,没有主体)。

The variables declared in an interface are public , static & final by default.
默认情况下,在接口中声明的变量是 publicstaticfinal

Syntax: Interfaces are declared by specifying a keyword interface .
句法:通过指定关键字 interface 来声明接口。

# Code sample

Movable Interface & Implementations
移动接口和实现

Suppose an application involves many objects that can move.
假设一个应用程序涉及许多可以移动的对象。

We could define an interface called movable , containing the signatures of the various movement methods.
我们可以定义一个称为 movable 的接口,其中包含各种移动方法的签名。

/* The Movable interface defines a list of public abstract methods to be implemented by its subclasses */
// use keyword "interface" (instead of "class") to define an interface
public interface Movable {  
	// An interface defines a list of public abstract methods to be implemented by the subclasses
	public void moveUp(); // "public" and "abstract" optional
	public void moveDown();
	public void moveLeft();
	public void moveRight();
}
// The subclass MovablePoint needs to implement all the abstract methods defined in the interface Movable
public class MovablePoint implements Movable {
	// Private member variables
	private int x, y;  // (x, y) coordinates of the point
	// Constructor
	public MovablePoint(int x, int y) {
		this.x = x; 
		this.y = y;
	}
	@Override
	public String toString() {
		return "(" + x + "," + y + ")";
	}
	// Need to implement all the abstract methods defined in the interface Movable
	@Override
	public void moveUp() {
		y--;
	}
	@Override
	public void moveDown() {
		y++;
	}
	@Override
	public void moveLeft() {
		x--;
	}
	@Override
	public void moveRight() {
		x++;
	}
}
public class TestMovable {
	public static void main(String[] args) {
		MovablePoint p1 = new MovablePoint(1, 2);  // upcast
		System.out.println(p1);
		p1.moveDown();
		System.out.println(p1);
		p1.moveRight();
		System.out.println(p1);
		// Test Polymorphism
		Movable p2 = new MovablePoint(3, 4);  // upcast
		p2.moveUp();
		System.out.println(p2);
		MovablePoint p3 = (MovablePoint)p2;   // downcast
		System.out.println(p3);
	}
}

# Upcasting & Downcasting

# Which should you use, abstract classes or interfaces?

  • Consider using abstract classes if any of these statements apply to your situation:
    如果以下任何一种情况适用于您的情况,请考虑使用抽象类:

    • You want to share code among several closely related classes.
      想在几个紧密相关的类之间共享代码。
    • You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private ).
      希望扩展抽象类的类具有许多公共方法或字段,或者需要除 public 之外的访问修饰符(例如 protectedprivate )。
    • You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.
      想要声明非 static 或非 final 字段。
      这样定义的方法,可以访问和修改所属对象的状态。
  • Consider using interfaces if any of these statements apply to your situation:
    如果以下任何一种情况适用于您的情况,请考虑使用接口:

    • You expect that unrelated classes would implement your interface.
      希望不相关的类将实现您的接口。
    • You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.
      想指定特定数据类型的行为,但不关心谁实现其行为。
    • You want to take advantage of multiple inheritance.
      想利用多重继承。

# Inheritance 继承

Inheritance is a process of defining a new class based on an existing class by extending its common data members and methods.
继承是通过扩展其公共数据成员和方法,基于现有类定义新类的过程。

Why use Inheritance?
Inheritance allows us to reuse of code, it improves reusability in your java application.
继承使我们可以重复使用代码,从而提高了 Java 应用程序的可重用性。
Advantage of use
Code that is already present in base class need not be rewritten in the child class.
基类中已经存在的代码无需在子类中重写。

# The "is a" Relationship

Inheritance has an "is-a" relationship.
继承具有 “is-a” 关系。

Inheritance
is a mechanism wherein a new class is derived from an existing class.
继承是一种机制,其中新类是从现有类派生的。
In Java, classes may inherit or acquire the properties and methods of other classes.
在 Java 中,类可以继承或获取其他类的属性和方法。
A class derived from another class is called a subclass, whereas the class from which a subclass is derived is called a superclass.
从另一个类派生的类称为子类,而从中派生子类的类称为超类。
Super Class: 超级类
The class whose features are inherited is known as super class (or a base class or a parent class).
被继承功能的类称为超级类(或基类或父类)。
Sub Class: 子类
The class that inherits the other class is known as sub class(or a derived class, extended class, or child class).
继承另一个类的类称为子类(或派生类,扩展类或子类)。
The subclass can add its own fields and methods in addition to the superclass fields and methods.
除了父类的字段和方法之外,子类还可以添加自己的字段和方法。
Reusability: 可重用性
Inheritance supports the concept of "reusability", i.e. when we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class.
继承支持 “可重用性” 的概念,即,当我们要创建一个新类并且已经有一个包含我们想要的某些代码的类时,我们可以从现有类中派生新类。
By doing this, we are reusing the fields and methods of the existing class.
通过这样做,我们可以重用现有类的字段和方法。
What to avoid? Too much dependency!
需要避免什么?太多的依赖!
Loose coupling better than tight coupling. High cohesion better than low cohesion.
松耦合优于紧耦合。高内聚力优于低内聚力。

# Types of Inheritance allowed.

允许的继承类型。

# Access privileges 访问权限

UML symbols:

- Private (encapsulation principle)
+ Public
# Protected

  • What is inherited?
    Protected members.
    Public methods.

  • What is not inherited?
    The constructor.
    Places object into an initial state!

# Types of Constructors

  1. System default (no arg), implicit calling.
    系统默认值,无参数,隐式调用
  2. Programmer defined, explicit calling
    程序员定义的,显式调用
  • No-arg 无参数
  • Parameterized (overloaded) 参数化(重载)

# toString() override

All classes in Java inherit from the Object class, directly or indirectly which contains the toString method.
Java 中的所有类都直接或间接地从包含 toString 方法的 Object 类继承。

We can override toString() method in any of our classes to print proper output specifying fields of a class.
我们可以在任何一个类中重写 toString() 方法,来打印指定类的正确输出。

To call the parent classes toString method definition, use the word super.
要调用父类的 toString 方法定义,请使用单词 super

# Object State

The state of an object encompasses all of the (usually static) properties of the object plus the current (usually dynamic) values of each of these properties.
对象的状态包含对象的所有属性(通常是静态),以及这些属性中每个属性的当前值(通常是动态)。

UML Class Diagram example

# Polymorphism 多态

Polymorphism is a OOPs concept where one name can have many forms.
多态是一个 OOP 概念,指一个名称可以具有多种形式。

For example, you have a smartphone for communication.
例如,您有用于通信的智能手机。
The communication mode you choose could be anything.
您选择的通信模式可以是任何东西。
It can be a call, a text message, a picture message, mail, etc.
它可以是电话,文本消息,图片消息,邮件等。
So, the goal is common that is communication, but their approach is different.
目标是共同的,即沟通,但是他们的方法不同。
This is called Polymorphism.
这称为多态。

Polymorphism deals with subtyping classes and gives us distinctive advantages at runtime.
多态处理子类型类,并在运行时为我们提供了独特的优势。

# Example

Consider our Bank Account example.
We have one parent class, Account with function of deposit and withdraw .
Account has 2 child classes.
The operation of deposit and withdraw is same for Saving and Checking accounts.
So the inherited methods from Account class will work.
例如我们的 Bank Account 示例。
我们有一个父类, Account 账户类,具有 deposit 存款和 withdraw 提现功能(两个方法)。
Account 帐户类有 2 个子类。
Saving 储蓄和 Checking 支票帐户类的 deposit 存款和 withdraw 提现操作相同。
因此,从 Account 类继承的方法将起作用。

Change in Software Requirement!?
There is a change in the requirement specification, something that is so common in the software industry.
更改软件需求!?
需求发生了变化,这在软件行业中很常见。

Example: You are supposed to add functionality with a privileged Banking Account with overdraft capabilities.
For a background, overdraft is a facility where you can withdraw an amount more than available the balance in your account.
So, a withdraw method for privileged class, needs to be implemented afresh.
But you do not change the tested piece of code in Savings and Checking account.
This is the advantage of OOPS!
示例:您要添加一个拥有透支功能的 Privileged 特权银行账户的功能。
透支功能是指可以提取比可用余额更多的金额。
因此,需要重新实现特权类的 withdraw 提现方法。
但是,不需要改动 Saving 储蓄和 Checking 支票帐户类中的已测代码段。
这就是 OOPS 的优势!

  1. Such that when the "withdraw" method for saving account is called a method from parent account class is executed.
    当调用 Saving 储蓄帐户的 withdraw 提现方法时,将执行父类 Account 帐户类中的方法。

  2. But when the "withdraw" method for the privileged account (overdraft facility) is called, the withdraw method defined in the privileged class is executed. This is Polymorphism.
    步骤 2)但是,当调用特权帐户的 withdraw 提现方法时,将执行 Privileged 特权类中定义的提现方法。 这就是多态。

# Key features

# Method Overriding

Method Overriding is redefining a super class method in a sub class.
是指在子类中重新定义父类的方法。

Rules for Method Overriding 规则

  • The method signature i.e. method name, parameter list and return type have to match exactly.
    方法的特征,如方法名、参数列表和返回值,必须完全一致
  • The overridden method can widen the accessibility, but not narrow it, i.e. if it is private in the base class, the child class can make it public but not vice versa.
    重写的方法可以扩大其可访问性,但不能缩小其可访问性,即,如果它在基类中是私有的,则子类可以将其公开,但反之则不然。

# super Keyword

Keyword super can be used to access methods of the parent class from the child class.
关键字 super 可用于从子类访问父类的方法。

What if the WITHDRAW method in the PRIVILEGED class wants to execute the functionality defined in ACCOUNT class and then perform its own specific functionality?
如果 Privileged 类中的 withdraw 方法要执行 Account 类中定义的功能,然后执行其自有的特定功能,该怎么办?

# final Keyword

The final modifier applies to classes, methods, and variables.
final 修饰符适用于类,方法和变量。

The meaning of final varies from context to context, but the essential idea is the same.
最终的含义因上下文而异,但是基本思想是相同的。

  • A final class may not be inherited
    final 类不会被继承

  • A final variable becomes a constant and its value cannot be changed.
    final 变量为常量,并且其值无法更改。

  • A final method may not be overridden. This is done for security reasons, and these methods are used for optimization.
    final 方法可能不会被覆盖。这是出于安全原因,并且这些方法用于优化。

# demo

  1. Construct a Polymorphism project and structure classes as follows
    构造一个多态项目并构造类,如下所示
Error: Failed to launch the browser process! spawn /Applications/Google Chrome.app/Contents/MacOS/Google Chrome ENOENT


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
  1. Add in special privileges to the Privileged class to override the withdraw method from the parent class and thus allow specific functionality to allow for the withdraw or not in the child class.
    在 Privileged 类中添加特殊特权,以覆盖父类的 withdraw 方法,从而允许特定功能允许子类中是否允许退出。

  2. Create AccountTest class to check implementation of the Privileged class.
    创建 AccountTest 类以检查 Privileged 类的实现。

Account.java
public class Account {
    protected String name;
    protected double balance;
    
    public Account(String name) {   
        this.name = name;      
    }
    public void deposit(double amount){
        this.balance += amount;
    }
    public void withdraw(double amount){
        this.balance  =  (balance-amount) < 0 ? 0 : (balance-amount);
    }
    public static void main(String[] args) {
        // TODO code application logic here
    }
    public String getName() { return name; }
    
    @Override
    public String toString(){
        return name + " " + "balance is " + balance ;
    }
}
Checking.java
public class Checking.java extends Account{
    public Checking () {
        super("Checking");        
    }
    @Override
    public String toString(){      
        return super.toString() ;
    }
}
Savings.java
public class Savings extends Account{
    public Savings () {
        super("Savings");
    }
    @Override
    public String toString(){      
        return super.toString() ;
    }
}
Privilege.java
public class Privilege extends Account{
    public Privilege () {
        super("Privilege");
    }
    //override the parent
    public void withdraw(double amount) {
        this.balance -= amount;
    }
}
AccountTest.java
public class AccountTest {
    public static void main(String args[]) {
        //create objects
        Checking c = new Checking();
        Savings s = new Savings();
        
        Account aObjs [] = new Account[5];
        aObjs[0]= new Checking();
        aObjs[1]= new Checking();
        aObjs[2]= new Checking();
        aObjs[3]= new Savings();
        aObjs[4]= new Privilege();
        
        //test withdraw
        aObjs[0].withdraw(5);
        aObjs[4].withdraw(10);
            
        //System.out.println(c + "\n" + s );
        int checkCt=0 , savCt=0;
        for (Account a :  aObjs)
        {
             if(a.getName().equals("Checking"))
                checkCt++;
             if(a.getName().equals("Savings"))
                savCt++;
            System.out.println(a);
        }
        System.out.println("Tots: \n" +
                  "Checking ct: " + checkCt +
                  " Savings ct: " + savCt );
    }
}

# Review

Chapter 6/7 OOP Concepts / Arrays / ArrayLists

  1. A constructor is a method that is automatically called when an object is created.

    构造函数是一种在创建对象时自动调用的方法。

  2. A constructor

    • Has return type of void
    • Always accepts two arguments
    • Always has an access specifier of private
    • Has the same name as the class

    构造函数

    • 返回类型为 void
    • 一律接受两个参数
    • 始终具有私有的访问权限
    • 与类同名 ✔️
  3. What is the default access specifier for methods and variables of a class?

    什么是类的方法和变量的 “默认” 访问权限说明符?
    Default access specifier for them both is package protected, that is, their accessibility is available to any other class but within the same package.
    它们的默认访问说明符都受程序包保护,也就是说,它们的可访问性可用于同一包中的任何其他类。

  4. For the following code, which statement is not true?

    public class Sphere {	
        private double radius;	
        public double x;	
        private double y;	
        private double z;
    }
    • z is available to code that is written outside the Sphere class
    • radius, x, y, and z are called members of the Sphere class
    • x is available to code that is written outside the Sphere class
    • radius is not available to code written outside the Sphere class

    对于以下代码,哪个语句不正确

    • z 可用于在 Sphere 类之外编写的代码 ✔️
    • radius,x,y 和 z 被称为 Sphere 类的成员
    • x 可用于在 Sphere 类之外编写的代码
    • radius 不适用于在 Sphere 类之外编写的代码
  5. What will be returned from the following method?

    public static int methodA() {
       double a = 8.5 + 9.5;
       return a;
    }

    以下方法将返回什么?
    This is an error

  6. What would be the results of the following code?

    final int SIZE = 5;
    int[] array1 = new int[SIZE];
    // ... Code that will put values in array1
    int value = 0;
    for (int a = 0; a <= array1.length; a++) {
       value += array1[a];
    }
    • value contains the lowest value in array1
    • value contains the sum of all the values in array1
    • value contains the highest value in array1
    • This would cause the program to crash

    以下代码的结果是什么?

    • 值包含 array1 中的最小值
    • value 包含 array1 中所有值的总和
    • 值包含 array1 中的最大值
    • 这会导致程序崩溃 ✔️
  7. The binary search algorithm

    • will cut the portion of the array being searched in half each time the loop fails to locate the search value
    • will have an average of N/2 comparisons, where N is the number of elements in the array
    • is less efficient than the sequential search algorithm
    • will have a maximum number of comparisons equal to the number of elements in the array

    二进制搜索算法

    • 每次循环未能找到搜索值时,将被搜索数组的部分减少一半。 ✔️
    • 将具有 N/2 个比较的平均值,其中 N 是数组中元素的数量
    • 比顺序搜索算法效率低
    • 将具有的最大比较数量等于数组中元素的数量
  8. If lower is the first subscript in a contiguous portion of an array, and upper is the last subscript, then the array item in the middle of that array portion is at subscript

    • (lower + upper)/2
    • (upper - lower)/2
    • (lower - upper)/2
    • lower + upper/2

    如果 lower 是数组连续部分中的第一个下标,而 upper 是最后一个下标,则该数组部分中间的数组项位于下标?

  9. The following statement creates an ArrayList object. What is the purpose of the <String> notation?

    ArrayList<String> arr = new ArrayList<String>();
    • It specfies that everything store for the arr object will be converted to a String
    • It specfies that String objects may not be stored in the ArrayList object
    • It specfies that only String objects may be stored in the ArrayList object
    • It specfies that the get method will only return String objects

    以下语句创建一个 ArrayList 对象。 <String> 表示法的目的是什么?

    • 确定将所有存储在 arr 对象中的东西都转换为 String
    • 确定 String 对象可能不存储在 ArrayList 对象中;
    • 规定只有 String 对象可以存储在 ArrayList 对象中; ✔️
    • 它指定 get 方法将仅返回 String ob
  10. The declaration

    ArrayList<int> aL = new ArrayList<int>();
    • compiles and runs correctly, but is not recommended
    • allows the programmer to create an ArrayList that holds integer types
    • causes a compile-time error
    • compiles correctly, but causes an exception to be thrown at run time
    • 正确编译并运行,但不建议
    • 允许程序员创建一个保存整数类型的 ArrayList
    • 导致编译时错误 ✔️
    • 正确编译,但导致在运行时引发异常