方法(计算机编程)

面向对象的编程(OOP)中的一种方法是与对象关联的过程,通常也是消息。一个对象由状态数据行为组成;这些构成了一个接口,该接口指定了如何使用对象。方法是用户参数参数的对象的行为。

数据表示为对象的属性,行为表示为方法。例如,Window对象可能具有诸如openclose,而其状态(无论是在任何给定时间点开放还是关闭)将是财产。

基于类的编程中,方法是在中定义的,对像是给定类的实例。方法提供的最重要功能之一是方法覆盖- 相同的名称(例如,area)可用于多种不同类型的类。这允许发送对象调用行为并将这些行为的实现委托给接收对象。 Java编程中的一种方法设置了类对象的行为。例如,一个对象可以发送area向另一个对象发送消息,并调用适当的公式是否是接收对像是一个rectangle,circle,triangle, ETC。

方法还提供了其他类用于访问和修改对象属性的接口;这被称为封装。封装和覆盖是方法和过程调用之间的两个主要区别特征。

覆盖和超载

方法覆盖过载是方法与常规过程或函数调用不同的两种最重要的方法。覆盖是指一个子类重新定义其超类方法的实现。例如,findArea可能是在形状类中定义的方法,triangle等等,每个都将定义适当的公式来计算其面积。这个想法是将对象视为“黑匣子”,以便对对象的内部更改可以对使用它的其他对象产生最小的影响。这被称为封装,旨在使代码更易于维护和重复使用。

另一方面,方法过载是指根据方法的参数来区分用于处理消息的代码。如果一个人将接收对象视为任何方法中的第一个参数,那么覆盖只是选择仅基于第一个参数的特殊情况。以下简单的Java示例说明了以下区别:

访问者,突变器和管理器方法

访问者方法用于读取对象的数据值。突变器方法用于修改对象的数据。经理方法用于初始化和破坏类的对象,例如构造函数和破坏者。

这些方法提供了一个促进封装模块化的抽象层。例如,如果银行帐户类提供getBalance()访问者方法可以检索当前余额(而不是直接访问余额数据字段),然后,同一代码的稍后修订可以实现更复杂的机制以进行余额检索(例如,数据库获取),而无需更改依赖的代码。封装和模块化的概念不是面向对象的编程所独有的。确实,从许多方面来说,面向对象的方法仅仅是先前范式的逻辑扩展,例如抽像数据类型结构化编程

构造函数

构造函数是一种在对像生命周期开始时调用的方法,用于创建和初始化对象,一个称为构造(或实例化)的过程。初始化可能包括对资源的收购。构造函数可能具有参数,但通常不会在大多数语言中返回值。请参阅Java中的以下示例:

public class Main {
    String _name;
    int _roll;
    Main(String name, int roll) { // constructor method
        this._name = name;
        this._roll = roll;
    }
}

驱动器

驱动器是一种在对像生命周期结束时自动称为的方法,一种称为破坏的过程。大多数语言中的破坏不允许destructor方法参数或返回值。可以在对象破坏时执行驱动器,以执行清理琐事和其他任务。

最终化器

垃圾收集的语言中,例如JavaC#Python ,破坏者被称为最终化器。它们的目的和功能与破坏者俱有类似的目的和功能,但是由于使用垃圾收集的语言之间的差异和具有手动内存管理的语言,因此称为它们的顺序是不同的。

抽象方法

一种抽象方法是一种只有一个签名,没有实现主体。通常用来指定子类必须像抽像类中一样提供该方法的实现。抽象方法用于指定某些编程语言中的接口

例子

以下Java代码显示了需要扩展的抽像类:

abstract class Shape {
    abstract int area(int h, int w); // abstract method signature
}

以下子类扩展了主要类:

public class Rectangle extends Shape {
    @Override
    int area(int h, int w) {
        return h * w;
    }
}

重新分解

如果子类为抽象方法提供实现,则另一个子类可以使其再次抽象。这称为重新提取

实际上,这很少使用。

例子

在C#中,可以使用抽象方法覆盖虚拟方法。 (这也适用于Java,其中所有非私有方法都是虚拟的。)

class IA
{
    public virtual void M() { }
}
abstract class IB : IA
{
    public override abstract void M(); // allowed
}

接口的默认方法也可以重新吸收,需要子类实现它们。 (这也适用于Java。)

interface IA
{
    void M() { }
}
interface IB : IA
{
    abstract void IA.M();
}
class C : IB { } // error: class 'C' does not implement 'IA.M'.

类方法

类方法是在而不是实例上调用的方法。它们通常用作对象元模型的一部分。 IE,对于每个类,都创建了元模型中的类对象的实例。元模型协议允许创建和删除类。从这个意义上讲,它们提供的功能与上述构造函数和破坏者相同。但是在某些语言中,例如通用LISP对象系统(CLOS),元模型允许开发人员在运行时动态更改对像模型:例如,创建新类,重新定义类层次结构,修改属性,等等。

特殊方法

特殊方法是非常特定的,语言可能支持此处定义的所有特殊方法。语言的编译器可以自动生成默认的特殊方法,也可以允许程序员可以选择定义特殊方法。大多数特殊方法无法直接调用,而是编译器生成代码在适当的时间调用它们。

静态方法

静态方法旨在与类的所有实例相关,而不是与任何特定实例有关。从这个意义上讲,它们类似于静态变量。一个示例将是一种静态方法,以总结类的每个实例的所有变量的值。例如,如果有一个Product类可能具有静态方法来计算所有产品的平均价格。

即使尚无类的实例,也可以调用静态方法。静态方法称为“静态”,因为它们是根据被调用的类解决的,而不是在实例方法中,而不是动态的,而不是在实例方法中,这些方法是根据对象的运行时类型来解决多态的。

例子

在爪哇

在Java中,一种常用的静态方法是:

Math.max(double a, double b)

这种静态方法没有所有对象,也没有在实例上运行。它从其论点中收到所有信息。

拷贝性分配操作员

复制分配运算符定义要由编译器执行的操作,当将类对象分配给同一类型的类对象时。

操作员方法

操作员方法定义或重新定义操作员符号,并定义要使用符号和关联的方法参数执行的操作。 C ++示例:

#include <string>
class Data {
 public:
  bool operator<(const Data& data) const { return roll_ < data.roll_; }
  bool operator==(const Data& data) const {
    return name_ == data.name_ && roll_ == data.roll_;
  }
 private:
  std::string name_;
  int roll_;
};

成员在C ++中的功能

扩展了一些程序语言,并具有面向对象的功能,以利用这些语言的大型技能和旧版代码,但仍然提供了面向对象的开发的好处。也许最著名的例子是C ++ ,这是C编程语言的面向对象的扩展。由于设计要求将面向对象的范式添加到现有的程序语言中,因此传递C ++的消息具有一些独特的功能和术语。例如,在C ++中,A方法称为成员函数。 C ++还具有虚拟函数的概念,该函数是成员函数,可以在派生类覆盖并允许动态调度

虚拟功能

虚拟函数是C ++类可以实现多态行为的手段。非虚拟成员功能常规方法是不参与多态性的方法。

C ++示例:

#include <iostream>
#include <memory>
class Super {
 public:
  virtual ~Super() = default;
  virtual void IAm() { std::cout << "I'm the super class!\n"; }
};
class Sub : public Super {
 public:
  void IAm() override { std::cout << "I'm the subclass!\n"; }
};
int main() {
  std::unique_ptr<Super> inst1 = std::make_unique<Super>();
  std::unique_ptr<Super> inst2 = std::make_unique<Sub>();
  inst1->IAm();  // Calls |Super::IAm|.
  inst2->IAm();  // Calls |Sub::IAm|.
}

也可以看看