oopoop入门


备注

面向对象编程(OOP)是一种基于“对象”概念的编程范例,它可能包含字段形式的数据,通常称为属性;代码,以程序的形式,通常称为方法。

介绍

OOP - 面向对象编程是目前广泛使用的编程范例。在OOP中,我们使用对象和行为来模拟现实世界中的问题,以便以编程方式解决它们。

有四个主要的OOP概念

  1. 遗产
  2. 多态性
  3. 抽象化
  4. 封装

这四个概念一起用于开发OOP程序。

有各种语言可以支持面向对象编程。最流行的语言是

  • C ++
  • Java的
  • C#
  • Python(Python不完全面向对象,但具有大部分OOP功能)

OOP简介

Intoduction

面向对象编程(主要称为OOP)是解决问题的编程范例。
OO(面向对象)程序的美妙之处在于,我们将程序视为一组彼此通信的对象,而不是遵循特定顺序的顺序脚本。

有很多支持OOP的编程语言,一些流行的是:

  • Java的
  • C ++
  • C#

众所周知,Python也支持OOP,但它缺少一些属性。


OOP术语

OOP中最基本的术语是一个
一个类基本上是一个对象 ,它有一个状态,它根据它的状态工作。

另一个重要的术语是一个实例
将类视为用于创建自身实例的模板。该类是一个模板,实例是具体的对象。

从类A创建的实例通常被称为“类型A”,类似于5的类型是int“abcd”的类型是字符串

创建名为insance1的类型(类) ClassA的实例的示例:

Java的

ClassA instance1 = new ClassA();
 

C ++

ClassA instance1;
 

要么

ClassA *instance1 = new ClassA(); # On the heap
 

蟒蛇

instance1 = ClassA()
 

正如您在上面的示例中所看到的,在所有情况下都提到了类的名称,之后有空括号(C ++除外,如果它们为空,则可以删除括号)。在这些括号中,我们可以将arguments 传递给我们类的构造函数

构造函数是每次创建实例时调用的类的方法。它既可以参与也可以不论证。如果程序员没有为他们构建的类指定任何构造函数,那么将创建一个空构造函数(一个什么都不做的构造函数)。
在大多数语言中,构造函数被定义为一种方法,没有定义其返回类型和类的相同名称(在几个部分中的示例)。

创建名为b1的类型(类) ClassB的实例的示例。 ClassB的构造函数接受一个int类型的参数:

Java的

ClassA instance1 = new ClassA(5);
 

要么

int i = 5;
ClassA instance1 = new ClassA(i);
 

C ++

ClassA instance1(5);
 

蟒蛇

instance1 = ClassA(5)
 

如您所见,创建实例的过程与调用函数的过程非常相似。


功能与方法

功能和方法都非常相似,但在面向对象设计(OOD)中它们各自都有其自身的含义。
方法是对类的实例执行的操作。该方法本身通常使用实例的状态来操作。
同时,函数属于类而不属于特定实例。这意味着它不使用类的状态或实例中存储的任何数据。

从现在开始,我们将仅在Java中展示我们的示例,因为OOP在这种语言中非常清晰,但是相同的原则适用于任何其他OOP语言。

在Java中,函数在其定义中包含单词static ,如下所示:

// File's name is ClassA
public static int add(int a, int b) {
    return a + b;
}
 

这意味着您可以从脚本中的任何位置调用它。

// From the same file
System.out.println(add(3, 5));

// From another file in the same package (or after imported)
System.out.println(ClassA.add(3, 5));
 

当我们从另一个文件调用该函数时,我们使用它所属的类的名称(在Java中,这也是文件的名称),这给出了函数属于类而不是它的任何实例的直觉。

相比之下,我们可以像这样在ClassA中定义一个方法:

// File's name is ClassA
public int subtract(int a, int b){
    return a - b;
}
 

在这个decleration之后我们可以像这样调用这个方法:

ClassA a = new ClassA();
System.out.println(a.subtract(3, 5));
 

这里我们需要创建一个ClassA实例,以便调用它的方法减法。请注意,我们不能执行以下操作:

System.out.println(ClassA.subtract(3, 5));
 

这行会产生一个编译错误,抱怨我们在没有实例的情况下调用了这个非静态方法。


使用类的状态

让我们假设我们想再次实现我们的减法方法,但这次我们总是想减去相同的数字(对于每个实例)。我们可以创建以下类:

class ClassB {

    private int sub_amount;

    public ClassB(int sub_amount) {
        this.sub_amount = sub_amount;
    }

    public int subtract(int a) {
        return a - sub_amount;
    }

    public static void main(String[] args) {
        ClassB b = new ClassB(5);
        System.out.println(b.subtract(3)); // Ouput is -2
    }
}
 

当我们运行这段代码,一个新的实例命名为BClassB的创建和它的构造被馈送值5。
构造函数现在接受给定的sub_amount并将其存储为自己的私有字段,也称为sub_amount (此约定在Java中非常有名,以将参数命名为与字段相同)。
之后,我们打印到控制台调用方法的结果减去 b的值为3

请注意,在执行减法时我们不使用this. 就像在构造函数中一样。
在Java中, this 只需要在有与该范围内定义的另一个同名变量被写入。这同样适用于Python的self
因此,当我们在减法中使用sub_amount时,我们引用每个类不同的私有字段。

另一个强调的例子。
我们只需将上面代码中的main函数更改为:

ClassB b1 = new ClassB(1);
ClassB b2 = new ClassB(2);

System.out.println(b1.subtract(10)); // Output is 9
System.out.println(b2.subtract(10)); // Output is 8
 

我们可以看到, b1b2是独立的,每个都有自己的状态


接口和继承

接口是一个契约,它定义了一个类将具有哪些方法,从而定义它的功能。接口没有实现,它只定义了需要完成的操作。
Java中的一个例子是:

interface Printalbe {
    public void print();
}
 

Printalbe接口定义了一个名为print的方法,但它没有给出它的实现(对于Java来说非常奇怪)。声明自己implementing 此接口的每个类都必须为draw方法提供实现。例如:

class Person implements Printalbe {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void print() {
        System.out.println(name);
    }
}
 

如果Person声明自己实现Drawable但没有提供打印实现,则会出现编译错误,程序无法编译。

继承是指向扩展另一个类的类的术语。例如,假设我们现在有一个有年龄的人。实现这样的人的一种方法是复制Person类并编写一个名为AgedPerson的新类,它具有相同的字段和方法,但它有另一个属性-age。
这很糟糕,因为我们复制整个代码只是为了给我们的类添加一个简单的特性。
我们可以使用继承继承Person ,从而获得它的所有功能,然后使用我们的新功能增强它们,如下所示:

class AgedPerson extends Person {

    private int age;

    public AgedPerson(String name, int age) {
        super(name);
        this.age = age;
    }

    public void print() {
        System.out.println("Name: " + name + ", age:" + age);
    }
}
 

有一些新的事情发生:

  • 我们使用保存的单词extends 来表示我们继承自Person(以及它的实现到Printable ,因此我们不需要再次声明implementing Printable )。
  • 我们所使用的保存字super 调用Person的构造函数。
  • 我们用一个新的覆盖了Person打印方法。

这是非常熟悉的Java技术,所以我不会深入研究这个主题。但是我会提到在开始使用它们之前应该学习很多关于继承和接口的极端情况。例如,哪些方法和函数是继承的?从类继承时,私有/公共/受保护字段会发生什么?等等。

抽象类

抽象类在OOP中是非常高级的术语,它描述了接口和继承的组合。它允许你编写一个具有已实现和未实现的方法/函数的类。在Java中,这是通过使用关键字abstract ,我不会更多地解释它是一个简单的例子:

abstract class AbstractIntStack {

    abstract public void push(int element);

    abstract public void pop();

    abstract public int top();

    final public void replaceTop(int element) {
        pop();
        push(element);
    }
}
 

注意: final 关键字表示从此类继承时无法覆盖此方法。如果一个类被声明为final,那么任何类都不能从它继承。