用户定义对象的类型转换

2023-12-21

就像我们对 __ToString 所做的那样,有没有办法定义转换方法?

$obj = (MyClass) $another_class_obj;

无需在 php 中输入强制类型转换。


Edit: 由于这个话题似乎引起了一些混乱,我想我应该详细说明一下。

在 Java 等语言中,有两种东西可以携带类型。编译器有一个关于类型的概念,而运行时有另一个关于类型的概念。编译器类型与变量绑定,而运行时引擎跟踪值的类型(分配给变量)。变量类型在编译时已知,而值类型仅在运行时已知。

如果一段输入代码违反了编译器的类型系统,编译器将呕吐并停止编译。换句话说,不可能编译出一段违反静态类型系统的代码。这可以捕获特定类别的错误。例如,采用以下(简化的)Java 代码:

class Alpha {}

class Beta extends Alpha {
  public void sayHello() {
    System.out.println("Hello");
  }
}

如果我们现在这样做:

Alpha a = new Beta();

我们会没事的,因为Beta是一个子类Alpha,因此变量的有效值a类型的Alpha。但是,如果我们继续这样做:

a.sayHello();

编译器会给出错误,因为该方法sayHello不是有效的方法Alpha- 不管我们知道a实际上是一个Beta.

输入类型转换:

((Beta) a).sayHello();

这里我们告诉编译器变量a在这种情况下,应该被视为Beta。这称为类型转换。这个漏洞非常有用,因为它允许语言中的多态性,但显然它也是各种违反类型系统的后门。为了保持某种类型安全,因此有一些限制;您只能转换为相关的类型。例如。在层次结构中向上或向下。换句话说,你将无法转换到完全不相关的类Charlie.

值得注意的是,所有这些都发生在编译器中 - 也就是说,它发生在代码运行之前。 Java 仍然可能出现运行时类型错误。例如,如果您这样做:

class Alpha {}

class Beta extends Alpha {
  public void sayHello() {
    System.out.println("Hello");
  }
}

class Charlie extends Alpha {}

Alpha a = new Charlie();
((Beta) a).sayHello();

上面的代码对于编译器来说是有效的,但是在运行时,你会得到一个异常,因为来自Beta to Charlie不兼容。

与此同时,回到 PHP 农场。

以下内容对 PHP 编译器有效 - 它会很乐意将其转换为可执行字节代码,但您会收到运行时错误:

class Alpha {}

class Beta extends Alpha {
  function sayHello() {
    print "Hello";
  }
}
$a = new Alpha();
$a->sayHello();

这是因为 PHP 变量没有类型。编译器不知道什么运行时类型对变量有效,因此它不会尝试强制执行它。您也不必像 Java 中那样显式指定类型。是的,有类型提示,但这些只是运行时合约。以下内容仍然有效:

// reuse the classes from above
function tellToSayHello(Alpha $a) {
  $a->sayHello();
}
tellToSayHello(new Beta());

尽管 PHP变量没有类型,values仍然如此。 PHP 的一个特别有趣的方面是可以更改值的类型。例如:

// The variable $foo holds a value with the type of string
$foo = "42";
echo gettype($foo); // Yields "string"
// Here we change the type from string -> integer
settype($foo, "integer");
echo gettype($foo); // Yields "integer"

此功能有时与类型转换相混淆,但这是用词不当。类型仍然是值的属性,并且类型更改发生在运行时 - 而不是在编译时。

PHP 中更改类型的能力也相当有限。只能在简单类型之间更改类型,而不能在对象之间更改类型。因此,不可能将类型从一个类更改为另一类。您可以创建一个新对象并复制状态,但无法更改类型。 PHP 在这方面有点局外人;其他类似的语言将类视为比 PHP 更加动态的概念。

PHP 的另一个类似功能是您可以将值克隆为新类型,如下所示:

// The variable $foo holds a value with the type of string
$foo = "42";
echo gettype($foo); // Yields "string"
// Here we change the type from string -> integer
$bar = (integer) $foo;
echo gettype($bar); // Yields "integer"

从语法上讲,这看起来很像静态类型语言中类型转换的编写方式。因此,它也经常与类型转换混淆,尽管它仍然是运行时类型转换。

总结一下:类型转换是一种更改变量类型的操作(not价值)。由于 PHP 中的变量没有类型,因此这不仅是不可能做到的,而且一开始就提出这个问题是无意义的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用户定义对象的类型转换 的相关文章

随机推荐

  • 在 VpnService.Builder 中传递用户名和密码的方法

    我正在开发想要使用 VPN 网络的应用程序 要在设备中创建 VPN 网络 我们需要从设备的 设置 无线和网络 VPN 设置 菜单中进行配置 我想通过带有硬编码信息的代码来完成这么多设置 从API级别4 0开始 android提供了API来处
  • mysql 返回表名

    假设我有这个mysql table structure table articles id content table news id news 有没有办法在这两个表中搜索字符串 然后如果出现该字符串则返回表的名称和行 id 假设两个表的
  • JPA 2.0:自动从不同的 jar* 添加实体类到 PersistenceUnit

    我有一个 Maven 构建的基于 CDI 的 Java SE 应用程序 它有一个core模块和其他模块 核心有persistence xml和一些实体 模块有额外的实体 如何将实体添加到持久性单元的聚光灯下 我读过 Hibernate 手册
  • 在 Devise Simple_Form_For 将新表单发布到 Devise 注册控制器中自定义到新用户注册页面的路由

    一个想法 我应该制作一个继承注册控制器的新控制器吗 然后再做另一个 devise for users controllers gt registration gt newcontroller 将我的 Trial signup html er
  • 如何检查字符串是否包含空格/字母数字/等字符?

    如何在 Swift 中使用 ctype h 库才能使用isAlpha or isSpace在人物上 或者有更好的 快速的方法吗 这个问题已得到解答 但似乎不起作用 Swift 如何确定字母是字母数字还是数字 https stackoverf
  • Heroku:从 MySQL 迁移数据库后 Postgres 类型运算符错误

    这是我之前提出的一个问题的后续问题 该问题更多地表述为编程问题而不是数据库问题 Heroku 上的 Sinatra Haml DataMapper 出现 Postgres 错误 https stackoverflow com questio
  • java中的ROT-13函数?

    是否已经有一个rot13 and unrot13 作为标准 Java 库之一的一部分实现 还是我必须自己写并 重新发明轮子 它可能看起来像这样 int rot13 int c if c gt A c lt Z c c A 13 26 A i
  • 在 laravel 4 中生成相对于基本 url 的 url

    我是 Laravel 的新手 现在正在 L 4 上构建一个应用程序 但卡在一个地方 无法理解如何生成相对于基本 url 的 url 在 laravel 3 中我知道这可以通过 url URL to user profile 但是 在 L 4
  • 在当前项目和插件组(本地、中央)中找不到前缀“jetty”的插件

    为了轻松运行我的 web 应用程序 我决定将 Jetty 添加到我的单个 POM 文件中 继官方文档 https www eclipse org jetty documentation 9 4 x maven and jetty html
  • Android Studio - 如何使用 getExternalFilesDir

    由于谷歌杀死了完美的方法 getExternalStoragePublicDirectory 我必须尝试让 getExternalFilesDir 工作 这是我尝试过的事情之一 private Context context this ge
  • 获取 Google App Engine 数据存储区中不属于列表的随机实体

    我正在使用 Google App Engine 构建网页游戏 游戏有一个存储的用户创建的关卡列表 可能很多 并且动态增加 并且每个用户都有一个他已经玩过的关卡列表 我需要为用户随机选择一个他以前没有玩过的级别 实体建模如下 class Us
  • 为什么 hibernate 给出 ConstraintException 就好像在对象已经存在时尝试创建对象一样

    我在更新 创建 CoverImage 对象时使用 saveOrUpdate 我偶尔会遇到主键约束冲突 org hibernate exception ConstraintViolationException Unique index or
  • 在docker容器中启用mysqli

    我使用以下代码构建一些容器 version 3 services db image mysql 5 7 environment MYSQL ROOT PASSWORD test MYSQL DATABASE test MYSQL USER
  • php整数和浮点比较不匹配

    我有以下代码 amount1 7299 amount2 72 9875 amount2 in cents round amount2 2 100 if amount1 amount2 in cents echo Amount amount1
  • Mysql排序分层数据

    我有一个问题 上周正在处理这个问题 但还无法解决 我可以使用 join 查询子菜单 但我无法订购它 我有一张这样的桌子 id name parent order 1 menu1 0 1 2 submenu1 1 2 3 submenu2 1
  • Django 中关系不存在错误

    我知道关于这个问题有很多问题 我查看了解决方案 不幸的是它们都不适合我 我创建了一个名为 用户管理 的新应用程序 并向该应用程序添加了一个模型 添加模型后 我将用户管理添加到设置中的 INSTALLED APPS 中 然后我运行 pytho
  • 如何用空格填充 NSString?

    例如 我需要 NSString 至少有 8 个字符 而不是使用循环在其上添加左侧填充空格 有没有办法做到这一点 Examples Input Output Hello Hello Bye Bye Very Long Very Long ab
  • 优化导致超时? [复制]

    这个问题在这里已经有答案了 我正在开发一个程序 该程序接受一个整数并查找该整数具有的连续总和的组合数量 数字13可以表示为连续正数之和 整数6 7 十四可以表示为2 3 4 5 也是一个和 连续正整数 有些数字可以表示为 以多种方式求连续正
  • 我知道回调函数是异步运行的,但为什么呢?

    语法的哪一部分提供了该函数应该在其他线程中运行并且是非阻塞的信息 让我们考虑一下 Node js 中的简单异步 I O var fs require fs var path process argv 2 fs readFile path u
  • 用户定义对象的类型转换

    就像我们对 ToString 所做的那样 有没有办法定义转换方法 obj MyClass another class obj 无需在 php 中输入强制类型转换 Edit 由于这个话题似乎引起了一些混乱 我想我应该详细说明一下 在 Java