PHP 面向对象编程 - 常见的关键字

本文围绕PHP展开,介绍了多个关键字。final关键字用于修饰类和方法,防止继承和重写;static关键字用于修饰类的成员属性和方法,可直接用类名访问;const用于在类中定义常量;instanceof用于检测对象实例所属类。还讲解了单例设计模式,保证一个类只有一个实例对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. final 关键字;

  • 在PHP5中新增加了 final 关键字,它只能用来修饰类和方法。不能使用 final 这个关键字来修饰成员属性。
  • final 的特性:
    • 使用 final 关键字标识的类不能被继承
    • 使用 final 关键字标识的方法不能被子类覆盖(重写),是最终版本
  • 目的:一是为了安全,二是没必要被继承或重写
  • 实例:demo.class.php
<?php

// final关键字修饰的类,是最终的类不能被继承

final class demo{

    // final关键字修饰的成员方法,是最终版本的方法不能被重写
   final public function say(){
        echo "demo say";
    }
    
}


class demo1 extends demo{

    public function say(){
        echo "demo1 say";
    }
}

// $d1 = new demo1();	// 报错
// $d1 -> say();		// 报错

2. static 关键字;

  • static 关键字表示静态的意思,用于修饰类的成员属性和成员方法(即静态属性和静态方法)。
  • 类中的静态属性和方法不用实例化对象(new)就可以直接使用类名访问。
# 格式
类::$静态属性
类::静态方法
  • 在类的方法中,不能用 $this 来引用静态变量或静态方法,而需要用 self 来引用。
# 格式
self::$静态属性
self::静态方法
  • 静态方法中不可以使用非静态的内容。就是不让使用 $this。
    • $this 代表本对象,而对象实例化出来是放在动态内存中,所以说它是非静态的内容,在静态方法中是不可以使用的
  • 静态属性是共享的。也就是 new 很多对象,很多对象都可以访问这个静态属性。
    • 在 PHP 核心语法中,声明自定义函数的时候,可以定义静态的变量,这个变量也是共享的。
    • 其中静态变量有一个很大的特性就是”只能初始化一次“。
  • 实例:demo.class.php
<?php

class demo{

    // static 如果修饰成员属性,这个成员属性就是静态的成员属性
    static public $name = "zhangsan";
    static public $num = 0;     // 静态的成员属性只能初始化一次。所有实例化的对象访问的都是同一个静态成员属性

    public function __construct(){
        self::$num++;
    }


    // static 如果修饰成员方法。这个方法就是静态的成员方法
    static public function say(){
        // self 代表本类
        return self::$name;     // 在类的内部访问静态成员属性  self::成员属性名
    }
}

echo demo::$name;       // 在类的外部访问静态的成员属性。类名::成员属性名
echo demo::say();       // 在类的外部访问静态的成员方法。类名::成员方法名

$d1 = new demo();
echo "<br />";
echo demo::$num;	// 输出1
$d2 = new demo();
echo "<br />";
echo demo::$num;	// 输出2

3. 单例设计模式;

  • 单例模式的主要作用是保证在面向对象编程设计中,一个类只能有一个实例对象存在。
  • 实例:db.class.php
# 用静态成员属性和静态成员方法实现单例设计模式(只能有一个对象)
# 注释操作步骤

# 让类不能外部实例化,把构造方法设置成私有(private)
# 声明一个静态(static)的 getObj() 的方法,它可以不需要对象就可以从类的外部访问。
# 声明这个方法的目的就是为了得到对象,怎么得到呢,new DB()。

# 接下去 var_dump(DB::getObj()),你会发现一样实例化成功了,构造方法已经执行,打印出了一个对象
# 然而再 var_dump(DB::getObj()),构造方法又运行了一次,证明了还是实例化了两次,不符合需求。

# 说明实例化的过程要有选择的实例化,用 if 来控制一下。
# 判断一下没有实例化的时候,就实例化一次,如果已经实例化,就直接返回实例化的结果。

# 设置一个静态(static)的成员属性 $obj = null
# 在 getObj() 里判断静态的成员属性($obj)为空的话,就实例化结果(new DB()),并赋给静态成员属性 $obj
# 因为静态属性只能初始化一次这个特性,第二次再调用 getObj() 的时候,$obj 的值就已经是对象了,对象直接返回就行。
# 此时会发现构造方法就只执行了一次,返回对象两次。
# 证明了不管调用多少次,实例化的过程只有一次,保证这个程序只有一个对象产生,这就是单例设计模式。

<?php

class DB{

    static $obj = null;     // 声明一个变量的成员属性。主要用静态成员属性只能初始化一次的特性,把它作为标识

    // 用于链接数据库
    private function __construct(){
        echo "mysql linked....";
    }

    // 静态的成员方法可以不需要对象就可以直接访问。这个方法用于得到对象
    static function getObj(){
        // 判断静态成员属性是否是初始值
        if(is_null(self::$obj)){
            // 如果是初始值。就实例化对象
            self::$obj =  new self(); 	// 把对象赋值给静态的成员属性
        }
        
        // 把静态成员属性中的对象返回
        return self::$obj;
    }

    public function select(){
        echo "select data....";
    }
}

var_dump(DB::getObj());
var_dump(DB::getObj());
var_dump(DB::getObj());

4. const 关键字;

  • const 是一个在类中定义常量的关键字,我们都知道在 PHP 中定义常量使用的是 define() 这个函数,但是在类里面定义常量使用的是 const 这个关键字
# 语法
# 不需要实例化对象即可获取

const CONSTANT = ‘constant value’; 	//定义
echo self::CONSTANT;				//类内部访问
echo className::CONSTANT; 			//类外部访问

  • 实例:demo.class.php
<?php

class demo{

    // 常量定义时就要赋初始值
    // 常量一但定义就不能修改
    // 如果是多个单词组成的常量名要用下划线分隔
    const HOST = '127.0.0.1';
    const DB_NAME = 'test';

    public function getConst(){
    
        // 在类的内部访问常量 self::常量名
        return self::DB_NAME;
    }
}


//在类的外部访问常量 类名::常量名
echo demo::HOST;
echo "<hr />";
$demo = new demo();
echo $demo -> getConst();

5. instanceof 关键字。

  • Instanceof 关键字用于检测用于检测当前对象实例是否属于某一个类或这个类的子类
  • 实例:demo.class.php
<?php

class demo{

}


class demo1 extends demo{

}


$demo = new demo();
$demo1 = new demo1();

// instanceof 可以用于判断一个对象是否由一个类或这个类子类实例化来的
var_dump($demo instanceof demo);
var_dump($demo1 instanceof demo1);
var_dump($demo instanceof demo1);
var_dump($demo1 instanceof demo);

<think>好的,我现在要解决用户在IAR编译器中遇到的错误:“incomplete type is not allowed”。首先,我需要理解这个错误的含义和常见原因。根据我的知识库,这个错误常发生在代码中使用了未完全定义的类型,比如结构体或联合体声明了但未定义,或者前向声明了某个类型但没有提供完整的定义。 首先,我应该检查用户代码中是否有结构体或联合体的声明但没有定义的情况。比如,如果有一个结构体声明为`struct MyStruct;`,但没有后续的完整定义,那么在需要该结构体大小或成员的地方,编译器就会报这个错误。这时候,需要用户补全结构体的定义,包括成员变量。 其次,检查是否在头文件中只声明了类型而没有包含定义。例如,如果在头文件中使用前向声明,但在使用该类型的源文件中没有包含实际的定义头文件,这也会导致错误。此时,需要确保在使用类型的地方包含了正确的头文件,或者将前向声明替换为完整的定义。 另外,还要考虑typedef的问题。如果用户使用了typedef创建别名,但原始类型未完全定义,同样会引发错误。例如,`typedef struct MyStruct MyType;`之后,如果尝试使用MyType但MyStruct尚未定义,就会出错。需要确保在使用typedef之前,原始类型已经被完整定义。 此外,数组声明中的类型不完整也是一个常见原因。比如声明数组时,如果元素类型未完全定义,编译器无法确定数组的大小,导致错误。需要检查数组声明中的类型是否已经完整定义。 可能还有其他情况,比如在C和C++混合编程时,如果没有正确使用extern "C",或者在头文件中遗漏了必要的包含,也可能导致类型不完整。需要用户检查这些方面。 接下来,我需要将这些可能的原因整理成清晰的解决步骤,并给出具体的代码示例,帮助用户理解如何修改。同时,根据用户提供的引用内容,虽然引用[1]和引用[2]是关于其他错误的,但用户可能希望看到类似的结构,即分点说明解决方案,并引用相关资源。 最后,生成相关问题,帮助用户进一步了解可能相关的编译错误,比如类型未定义、前向声明问题等。这样用户可以有更全面的认识,预防其他类似错误的发生。</think>### IAR编译器错误'incomplete type is not allowed'解决方案 该错误表示代码中使用了**未完全定义的类型**,编译器无法确定其内存布局或成员信息。以下是具体原因及解决方法: #### 1. 结构体/联合体未定义完整 若声明了结构体但未定义成员,在实例化时会报错: ```c struct MyStruct; // 前向声明不完整 struct MyStruct var; // 错误:使用未完成类型 ``` **解决方案**:补全类型定义 ```c struct MyStruct { int id; char name[20]; }; ``` #### 2. 头文件包含缺失 当跨文件使用类型时,需确保定义可见: ```c // file.h struct Data; // 前向声明 // file.c struct Data { // 实际定义 int value; }; ``` **解决方案**:在使用该类型的文件中包含定义头文件 ```c #include "file.c" // 包含实际定义 ``` #### 3. typedef别名问题 使用typedef时原始类型必须完整: ```c typedef struct Node NodeT; // 前向声明 NodeT* ptr; // 允许指针声明 NodeT instance; // 错误:不完整类型 ``` **解决方案**:先完成类型定义再typedef ```c struct Node { int data; struct Node* next; }; typedef struct Node NodeT; ``` #### 4. 数组声明不完整 数组元素类型必须完全定义: ```c struct Element; struct Element arr[10]; // 错误:元素类型未定义 ``` **解决方案**: ```c struct Element { int type; float value; }; struct Element arr[10]; // 合法 ``` #### 调试建议 1. 在IAR工程中搜索错误行号定位问题代码 2. 使用Go to Definition功能追踪类型定义 3. 检查所有头文件包含链 4. 确认没有循环依赖的头文件 编译器需要知道类型的完整信息才能: - 计算sizeof大小 - 分配内存空间 - 访问成员变量 - 进行类型对齐 [^1]: 类似类型转换错误可参考浮点转整型的类型适配问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值