PHP面向对象面试题

1、简述面对对象六大设计原则 ?

面向对象六大设计原则是一组指导软件设计的原则,它们有助于提高代码的可维护性、可扩展性和可重用性。这些原则是:

  1. 单一职责原则(Single Responsibility Principle,SRP):  一个类应该只有一个引起它变化的原因。 换句话说,一个类应该只有一个职责,只负责一件事情。
  2. 开放封闭原则(Open-Closed Principle,OCP):                                                                软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改原有代码。
  3. 里氏替换原则(Liskov Substitution Principle,LSP):                                                          子类应该能够替换父类并且不会破坏程序的正确性。换句话说,任何可以使用父类对象的地方,都应该能够使用子类对象,而不会产生意外的结果。
  4. 依赖倒置原则(Dependency Inversion Principle,DIP):                                                   高层模块不应该依赖于低层模块,而是应该依赖于抽象。具体而言,应该通过接口或抽象类来定义依赖关系,而不是直接依赖于具体实现。
  5. 接口隔离原则(Interface Segregation Principle,ISP):                                                    客户端不应该强迫依赖于它们不需要的接口。换句话说,应该将接口细化为更小的接口,以便客户端只需要依赖于它们实际需要的方法。
  6. 迪米特法则(Law of Demeter,LoD):                                                                                  一个对象应该只与其直接的朋友进行交互,不应该与陌生人进行交互。换句话说,一个对象应该尽量减少与其他对象的依赖关系,尽量只依赖于自己的直接关系。 这些设计原则提供了一种指导软件设计的方法,帮助开发人员写出高质量、可维护的代码。

 2、简述 private、 protected、 public修饰符的访问权限 ?

private、protected和public是面向对象编程中常用的访问修饰符,用于控制类的成员(属性和方法)的访问权限。

  1. private修饰符:private表示私有的,只能在当前类内部访问。私有成员对于类外部是不可见的,其他类无法直接访问私有成员。私有成员主要用于封装类的内部细节,提高封装性和安全性。
  2. protected修饰符:protected表示受保护的,可以在当前类和其子类中访问。受保护成员对于类外部是不可见的,但对于子类是可见的。受保护成员主要用于实现继承和多态,子类可以通过继承父类的受保护成员来访问和使用。
  3. public修饰符:public表示公共的可以在任何地方访问。公共成员对于所有类都是可见的,其他类可以直接访问公共成员。公共成员主要用于提供给外部调用的接口,使其它类可以访问和使用。 通过使用这些修饰符,可以灵活地控制类的成员的访问权限,实现封装、继承和多态的特性,同时也可以提高代码的可维护性和可扩展性。正确使用这些修饰符可以帮助我们设计出更加健壮和灵活的面向对象的代码。

3、请写出PHP的构造函数和析构函数、区别?

PHP的构造函数和析构函数是两个特殊的方法,用于在创建和销毁对象时执行一些初始化和清理操作。 构造函数: 构造函数是在创建对象时自动调用的方法。它的名称与类名相同,没有返回类型,并且不能显式调用。构造函数主要用于初始化对象的属性和执行一些必要的设置。在PHP中,构造函数使用关键字__construct来定义。 示例代码:

class MyClass {
    public function __construct() {
        // 构造函数的初始化操作
    }
}
$obj = new MyClass(); // 创建对象时自动调用构造函数

析构函数: 析构函数是在对象被销毁时自动调用的方法。它的名称也是与类名相同,但前面加上两个下划线__,没有参数和返回值。析构函数主要用于执行一些清理操作,例如释放资源、关闭数据库连接等。在PHP中,析构函数使用关键字__destruct来定义。 示例代码:

class MyClass {
    public function __destruct() {
        // 析构函数的清理操作
    }
}
$obj = new MyClass();
// 对象在作用域结束时自动调用析构函数,或者可以通过 unset($obj) 手动销毁对象并触发析构函数。

区别:

  1. 构造函数是在对象创建时自动调用的,而析构函数是在对象被销毁时自动调用的。
  2. 构造函数用于初始化对象的属性和执行一些必要的设置,而析构函数用于执行一些清理操作。
  3. 构造函数没有返回类型,而析构函数也没有参数和返回值。
  4. 构造函数不能显式调用,而析构函数可以通过手动销毁对象或对象作用域结束来触发。 构造函数和析构函数在面向对象编程中起着重要的作用,它们帮助我们在对象的生命周期中进行必要的初始化和清理操作,提高代码的可维护性和可靠性。

4、PHP 中对象是按值传递还是按引用传递?

在 PHP 中,对象是按引用传递的。这意味着当将一个对象赋值给另一个变量或将对象作为参数传递给函数时,实际上是传递对象的引用,而不是对象的副本。 当对象被赋值给一个新的变量时,两个变量将引用同一个对象。对其中一个变量所做的更改也会影响到另一个变量。 示例代码:

class MyClass {
    public $property;
}
$obj1 = new MyClass();
$obj1->property = 'Value';
$obj2 = $obj1; // 将$obj1赋值给$obj2
$obj2->property = 'New Value';
echo $obj1->property; // 输出 "New Value"

 在上述示例中,修改 $obj2property 属性后,$obj1property 属性也被修改了,因为它们引用同一个对象。 需要注意的是,PHP 中的基本类型(如整数、字符串等)是按值传递的,而对象是按引用传递的。这是因为对象在内存中是通过指针进行引用的,而基本类型是直接存储在变量中。 通过理解 PHP 中对象的传递方式,可以更好地控制和管理对象的使用,避免不必要的副作用。

5、PHP 面对对象设计OOP具有三大特点 ?

PHP面向对象设计(OOP)具有以下三大特点:

  1. 封装(Encapsulation):封装是指将对象的属性(数据)和行为(方法)封装在一起,形成一个独立的、可复用的对象。通过封装,可以隐藏对象的内部实现细节,只暴露必要的接口给外部使用。这样可以提高代码的安全性、可维护性和可重用性。
  2. 继承(Inheritance):继承是指一个类可以继承另一个类的属性和方法。通过继承,可以创建一个新的类,继承已有类的属性和方法,并且可以在新的类中添加额外的属性和方法。继承可以实现代码的重用,减少代码的冗余,同时也方便了代码的扩展和维护。
  3. 多态(Polymorphism):多态是指同一种操作可以在不同的对象上有不同的行为。在面向对象编程中,多态通过继承和接口实现。多态可以提高代码的灵活性和可扩展性,使代码更加通用和易于维护。 这三个特点是面向对象编程的基石,它们使得代码更加模块化、可维护性更高、可重用性更好,并且能够更好地应对复杂的业务逻辑和需求变化。在PHP中,面向对象编程可以通过类、对象、属性、方法、继承、接口等语言特性来实现。

6、PHP支持多继承吗? 

PHP 不直接支持多继承。多继承是指一个类可以同时继承多个父类的属性和方法。然而,PHP通过使用接口(interface)和特质(trait)来模拟多继承的部分功能。

  1. 接口(interface):接口是一种抽象的类,其中只定义了方法的签名而没有具体的实现。一个类可以实现多个接口,从而获得多个接口中定义的方法。接口允许一个类具备多个接口的行为,但并不提供属性的继承。
  2. 特质(trait):特质是一种可以被多个类共享的代码块。类可以通过使用特质来复用特定的方法集合。一个类可以使用多个特质,并且特质可以相互组合。特质允许一个类具有多个特质中定义的方法和属性。 通过接口和特质的组合,可以在 PHP 中模拟多继承的部分功能。但需要注意的是,PHP 的多继承模拟并不像一些其他编程语言中的原生多继承那样简单和直接。在使用接口和特质时,需要谨慎设计和管理类的继承关系,以避免引入复杂性和冲突。

7、PHP子类如何调用父类构造方法 ? 

在 PHP 中,子类可以通过使用 parent::__construct() 方法来调用父类的构造方法。这个方法可以在子类的构造方法中使用,用于执行父类的构造方法。 下面是一个示例代码:

class ParentClass {
    public function __construct() {
        echo "ParentClass 构造方法被调用";
    }
}
class ChildClass extends ParentClass {
    public function __construct() {
        parent::__construct(); // 调用父类的构造方法
        echo "ChildClass 构造方法被调用";
    }
}
$child = new ChildClass();

在上述代码中,ChildClass 继承了 ParentClass,并且在子类的构造方法中通过 parent::__construct() 调用了父类的构造方法。当创建子类的实例时,首先会执行父类的构造方法,然后再执行子类的构造方法。 需要注意的是,如果子类没有定义自己的构造方法,那么可以省略 parent::__construct() 的调用,因为子类会自动调用父类的构造方法。但如果子类自己定义了构造方法,并且想要调用父类的构造方法,就需要显式地使用 parent::__construct() 来调用父类的构造方法。

8、面向对象中接口和抽象类的区别及应用场景?

接口(Interface)和抽象类(Abstract Class)是面向对象编程中的两个重要概念。它们有以下区别和应用场景:

  1. 区别:
    • 定义:接口是一种完全抽象的类,其中只定义了方法的签名而没有实现;抽象类是一种可以包含具体方法实现和抽象方法的类。
    • 实现方式:一个类可以实现多个接口,但只能继承一个抽象类。
    • 方法:接口只能定义公共方法,抽象类可以定义公共和受保护的方法。
    • 属性:接口不能定义属性,抽象类可以定义属性。
    • 实例化:接口不能被实例化,抽象类不能直接实例化,需要通过子类继承后实例化。
  2. 应用场景:
    • 接口:适用于定义类的契约和行为规范,可以被多个类实现。接口强调对行为的定义,用于实现类的多态性和解耦。
    • 抽象类:适用于定义某个类的通用行为和属性,可以被子类继承。抽象类可以提供默认的方法实现,同时也可以定义抽象方法,要求子类必须实现。 接口和抽象类的使用场景有一定的重叠,但在实际应用中可以根据具体需求进行选择:
  • 当需要定义类的行为规范和约束时,使用接口。例如,定义一个可飞行的接口,多个类实现该接口,实现飞行的功能。
  • 当需要定义类的通用行为和属性,并且希望子类必须实现某些方法时,使用抽象类。例如,定义一个动物类的抽象类,其中定义了通用的方法,子类必须实现具体的动物行为。 总的来说,接口强调对行为的定义,用于实现类的多态性和解耦;抽象类强调对类的通用行为和属性的定义,可以提供默认的方法实现,并要求子类必须实现某些方法。

9、常用的魔术方法有哪些?举例说明

php规定以两个下划线(__)开头的方法都保留为魔术方法,所以建议大家函数名最好不用__开头,除非是为了重载已有的魔术方法。 

__construct() 实例化类时自动调用。

__destruct() 类对象使用结束时自动调用。

__set() 在给未定义的属性赋值的时候调用。

__get() 调用未定义的属性时候调用。

__isset() 使用isset()或empty()函数时候会调用。

__unset() 使用unset()时候会调用。

__sleep() 使用serialize序列化时候调用。

__wakeup() 使用unserialize反序列化的时候调用。

__call() 调用一个不存在的方法的时候调用。

__callStatic()调用一个不存在的静态方法是调用。

__toString() 把对象转换成字符串的时候会调用。比如 echo。

__invoke() 当尝试把对象当方法调用时调用。

__set_state() 当使用var_export()函数时候调用。接受一个数组参数。

__clone() 当使用clone复制一个对象时候调用 

10、简述作用域操作符::如何使用?都在哪些场合下使用? 

作用域操作符 :: 在 PHP 中用于访问类的常量、静态属性和静态方法。它的使用方式如下:

  1. 访问类的常量:使用 类名::常量名 的语法来访问类的常量。常用于获取类的配置信息或者定义一些全局常量。例如:
    class MyClass {
        const MY_CONSTANT = 123;
    }
    echo MyClass::MY_CONSTANT; // 输出:123

  2. 访问静态属性:使用 类名::$静态属性名 的语法来访问类的静态属性。静态属性是类的属性,不依赖于类的实例化,可以在任何地方访问。例如:
    class MyClass {
        public static $myProperty = "Hello";
    }
    echo MyClass::$myProperty; // 输出:Hello

  3. 调用静态方法:使用 类名::静态方法名() 的语法来调用类的静态方法。静态方法是类的方法,不依赖于类的实例化,可以直接通过类名调用。例如:
    class MyClass {
        public static function myMethod() {
            echo "Hello";
        }
    }
    MyClass::myMethod(); // 输出:Hello

    作用域操作符 :: 主要在以下场合下使用:

  4. 访问类的常量:通过类名访问类的常量,而不需要实例化类对象。
  5. 访问静态属性:通过类名访问类的静态属性,而不需要实例化类对象。
  6. 调用静态方法:通过类名调用类的静态方法,而不需要实例化类对象。 在这些场合下,作用域操作符 :: 提供了一种直接访问和调用类的静态成员的方式,方便在不实例化对象的情况下进行操作。

11、简述PHP面向对象接口和使用场景 

在 PHP 中,接口是一种抽象的定义,它规定了一个类应该具有的方法。一个类可以实现一个或多个接口,通过实现接口中定义的方法,来实现对接口的约束和规范。接口使用 interface 关键字来定义。 接口的使用场景包括:

  1. 规范类的行为:接口可以定义一组方法,用于规范类的行为。当一个类实现了某个接口,就表示该类具有了接口中定义的方法,从而实现了对行为的规范。
  2. 多态性:接口可以作为类型来使用。当一个类实现了某个接口,就可以将该类的实例赋值给接口类型的变量,实现多态性。这样可以在不关心具体类的情况下,统一对不同类的实例进行操作。
  3. 代码复用和扩展:接口提供了一种约定,要求实现类必须实现接口中定义的方法。通过接口,可以将一些通用的方法定义在接口中,然后多个类实现该接口,实现代码的复用。当需要增加新的功能时,只需要在接口中新增方法,而不需要修改已有的类。
  4. 与其他代码的解耦:接口可以用于解耦代码之间的依赖关系。通过面向接口的编程,可以将接口定义的方法作为公共接口,不同的类实现该接口,从而降低类与类之间的耦合度。 以下是一个使用接口的示例:
    interface Animal {
        public function eat();
        public function sleep();
    }
    class Cat implements Animal {
        public function eat() {
            echo "Cat is eating";
        }
        public function sleep() {
            echo "Cat is sleeping";
        }
    }
    class Dog implements Animal {
        public function eat() {
            echo "Dog is eating";
        }
        public function sleep() {
            echo "Dog is sleeping";
        }
    }
    $cat = new Cat();
    $dog = new Dog();
    $cat->eat(); // 输出:Cat is eating
    $dog->eat(); // 输出:Dog is eating

    在上述示例中,Animal 是一个接口,定义了 eat()sleep() 两个方法。CatDog 类都实现了 Animal 接口,并实现了接口中定义的方法。通过接口,可以统一对不同类的实例进行操作,实现了多态性和代码的复用。

12、简述PHP Static和Final 关键字与使用场景 ? 

在 PHP 中,staticfinal 是两个关键字,用于修饰类的属性、方法和常量。它们的使用场景如下:

  1. static 关键字:
    • 静态属性:使用 static 关键字声明的属性是类属性,而不是实例属性。它们不依赖于类的实例化,可以在任何时候访问。静态属性可以用于保存类的共享数据或者全局配置信息。
    • 静态方法:使用 static 关键字声明的方法是类方法,而不是实例方法。它们不依赖于类的实例化,可以直接通过类名调用。静态方法可以用于执行与类相关的操作,而不需要创建类的实例。
    • 静态常量:使用 const 关键字声明的常量是类的常量,可以通过 类名::常量名 的方式访问。静态常量一般用于定义一些固定不变的值,例如配置信息或者标识符。
  2. final 关键字:
    • final 类:使用 final 关键字声明的类是最终类,不能被继承。当一个类不希望被其他类继承时,可以将该类声明为 final 类。
    • final 方法:使用 final 关键字声明的方法是最终方法,不能被子类重写。当一个类的某个方法不希望被子类重写时,可以将该方法声明为 final 方法。 使用场景:
  • static 关键字的使用场景:
    • 静态属性:用于保存类的共享数据或者全局配置信息。
    • 静态方法:用于执行与类相关的操作,而不需要创建类的实例。
    • 静态常量:用于定义一些固定不变的值,例如配置信息或者标识符。
  • final 关键字的使用场景:
    • final 类:用于禁止其他类继承该类,保护类的完整性和稳定性。
    • final 方法:用于禁止子类重写该方法,确保方法的一致性和稳定性。 需要注意的是,staticfinal 关键字是可选的,根据实际需求来决定是否使用。在使用时,需要根据具体的业务场景和设计需求来合理应用这两个关键字。

你可能感兴趣的:(面试,php,php,开发语言)