在PHP中构建MVC框架后,我遇到了一个问题,可以使用Java样式泛型轻松解决。抽象的Controller类可能看起来像这样:
abstract class Controller {
abstract public function addModel(Model $model);
在某些情况下,Controller类的子类只能接受Model的子类。例如,ExtendedController应该只将ReOrderableModel接受到addModel方法中,因为它提供了ExtendedController需要访问的reOrder()方法:
class ExtendedController extends Controller {
public function addModel(ReOrderableModel $model) {
在PHP中,继承的方法签名必须完全相同,因此即使类继承了超类中暗示的类类型,也不能将类型提示更改为其他类。在Java中,我只需这样做:
abstract class Controller<T> {
abstract public addModel(T model);
class ExtendedController extends Controller<ReOrderableModel> {
public addModel(ReOrderableModel model) {
但是PHP没有泛型支持。是否有任何解决方案仍将遵循OOP原则?
编辑
我知道PHP根本不需要类型提示,但是它可能是糟糕的OOP。首先,从接口(方法签名)尚不清楚应接受哪种对象。因此,如果另一个开发人员想要使用该方法,则很明显,需要类型X的对象,而不必通过无效的封装(破坏了信息隐藏原理)来查看实现(方法主体)。其次,由于没有类型安全性,因此该方法可以接受任何无效变量,这意味着到处都需要手动类型检查和异常抛出!
它对于以下测试用例似乎很有效(尽管它确实发出了严格警告):
class PassMeIn
{
}
class PassMeInSubClass extends PassMeIn
{
}
class ClassProcessor
{
public function processClass (PassMeIn $class)
{
var_dump (get_class ($class));
}
}
class ClassProcessorSubClass extends ClassProcessor
{
public function processClass (PassMeInSubClass $class)
{
parent::processClass ($class);
}
}
$a = new PassMeIn;
$b = new PassMeInSubClass;
$c = new ClassProcessor;
$d = new ClassProcessorSubClass;
$c -> processClass ($a);
$c -> processClass ($b);
$d -> processClass ($b);
如果严格警告不是您真正想要的,则可以这样解决。
class ClassProcessor
{
public function processClass (PassMeIn $class)
{
var_dump (get_class ($class));
}
}
class ClassProcessorSubClass extends ClassProcessor
{
public function processClass (PassMeIn $class)
{
if ($class instanceof PassMeInSubClass)
{
parent::processClass ($class);
}
else
{
throw new InvalidArgumentException;
}
}
}
$a = new PassMeIn;
$b = new PassMeInSubClass;
$c = new ClassProcessor;
$d = new ClassProcessorSubClass;
$c -> processClass ($a);
$c -> processClass ($b);
$d -> processClass ($b);
$d -> processClass ($a);
不过,您应该记住一件事,这绝对不是OOP方面的最佳实践。如果超类可以接受特定类的对象作为方法参数,则其所有子类也应也可以接受该类的对象。防止子类处理超类可以接受的类意味着您不能使用子类代替超类,并且要100%确信它在所有情况下都可以使用。相关实践称为Liskov替代原理,它指出,除其他外,方法参数的类型只能在子类中变弱,而返回值的类型只能变强(输入只能变得更通用,输出可以仅获得更具体的信息)。
这是一个非常令人沮丧的问题,我本人已经多次尝试反对它,因此,如果在特定情况下忽略它是最好的选择,那么我建议您忽略它。但是请不要养成它的习惯,否则您的代码将开始开发各种微妙的相互依赖关系,这将是调试的噩梦(单元测试无法捕获它们,因为各个单元的行为均符合预期,这是它们之间的相互作用问题所在)。如果您确实忽略了它,那么请注释该代码以使其他人知道它,这是一个有意的设计选择。
问题内容: 所以我有一张地图: 我会像这样添加元素: 我有如下通用方法: 现在,这段代码可以很好地工作,并且没有编译器问题: 但是,当我尝试这样做时: 编译器向我显示以下警告:类型安全:通用方法verifyType(String,Class)的未经检查的调用verifyType(String,Class) 这让我感到困惑…请帮助… 问题答案: 更改: 至 通过仅将类型声明为“ Class”,就失去
现在,当我在地图上迭代时…我能以某种方式获得每个Class1对象的类型(K,V)吗??
如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或
嗨,我是概念数据建模的新手,目前正在研究实体关系图。只是一些我找不到答案的问题: > 我正在设计一个基于给定场景的E-R图,当我将我的答案与“模型答案”进行匹配时,它是非常不同的,特别是我在代表两个实体之间关系的菱形形状中使用的术语。我这样说对吗?只要是合乎逻辑的,代表这种关系的词语的选择就可以是任何东西? 我注意到不同的教程使用不同的表示基数的方法。有的用鱼尾纹,有的用M:N表示多对多。既然有这
我不想为每个类型T编写这个方法只是为了调用getMessage()并将其传递给下一个方法。 有可能写出这样的方法吗?我只想访问ConstraintViolation接口的方法,这些方法不依赖于类型T(如字符串getMessage())。
问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符