Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使抽象类方法只能从子类公开访问_Php_Encapsulation_Abstraction_Php 7.4 - Fatal编程技术网

Php 使抽象类方法只能从子类公开访问

Php 使抽象类方法只能从子类公开访问,php,encapsulation,abstraction,php-7.4,Php,Encapsulation,Abstraction,Php 7.4,首先,我们讨论的是PHP7.4.10,但是任何通用的英特尔都会接受 总结问题:我想在抽象类中定义一个静态方法,该方法只能从扩展抽象类的子类公开调用,而不能从抽象类本身公开调用。对不起,如果我在这里说得太简单了,但我确实已经花了几个小时寻找答案,甚至找不到关于这个话题的任何讨论 让我们在评论中考虑下面的例子。我希望能够调用Apple::printName和Pear::printName,但不能调用Fruit::printName 对于如何实现期望的行为,我也愿意接受任何替代方法 public st

首先,我们讨论的是PHP7.4.10,但是任何通用的英特尔都会接受

总结问题:我想在抽象类中定义一个静态方法,该方法只能从扩展抽象类的子类公开调用,而不能从抽象类本身公开调用。对不起,如果我在这里说得太简单了,但我确实已经花了几个小时寻找答案,甚至找不到关于这个话题的任何讨论

让我们在评论中考虑下面的例子。我希望能够调用Apple::printName和Pear::printName,但不能调用Fruit::printName

对于如何实现期望的行为,我也愿意接受任何替代方法

public static function printName() {}
这是一个具体方法的定义。有人可能认为调用这个方法是可以的,因为它是非抽象的公共方法。那么,如果水果对它没有任何作用,为什么它会有呢

所以一个解决办法就是定义一个特征,并且只在那些真正需要它的人里面使用它

然而,如果您的水果只是一个子类的定义,就像您在评论中提到的,并且您碰巧有PHP8:那么可能只是不使printName成为静态的

现在echo Fruit::printName;会给你一个你一直在寻找的致命错误

致命错误:未捕获错误:非静态方法Fruit::printName 不能静态调用

这是一个具体方法的定义。有人可能认为调用这个方法是可以的,因为它是非抽象的公共方法。那么,如果水果对它没有任何作用,为什么它会有呢

所以一个解决办法就是定义一个特征,并且只在那些真正需要它的人里面使用它

然而,如果您的水果只是一个子类的定义,就像您在评论中提到的,并且您碰巧有PHP8:那么可能只是不使printName成为静态的

现在echo Fruit::printName;会给你一个你一直在寻找的致命错误

致命错误:未捕获错误:非静态方法Fruit::printName 不能静态调用


您可以检查您的实例是否为子类,如果不是子类,则可以退出

抽象类A1{ 公共静态函数{ return是新static“A1”的子类; } } A2类延伸至A1类{ } Al::childrenOnly;//出错 A2::仅限儿童;//符合事实的
您可以检查您的实例是否为子类,如果不是子类,则可以退出

抽象类A1{ 公共静态函数{ return是新static“A1”的子类; } } A2类延伸至A1类{ } Al::childrenOnly;//出错 A2::仅限儿童;//符合事实的
所以在阅读了所有的答案后,我想出了一个解决办法,最终决定支持@chilliNUT的建议。我最后进行了如下工作:

abstract class Fruit
{
    protected abstract static function name() : string;

    /*
     * Basically, if you call the default method from any child (not necessarily a direct child) class, no problems,
     * but if you call it directly from the baseclass, you get the somewhat acceptable exception :)
     */
    public static function printName()
    {
        if(!is_subclass_of(static::class, self::class))
        {
            throw new \BadMethodCallException("Can't call base Fruit class methods directly!");
        }

        return "My name is: " . static::name();
    }
}

//those are abstract now, just to match the intention of them being utility singletons
abstract class Apple extends Fruit
{
    protected static function name() : string
    {
        return "apple";
    }
}

abstract class Pear extends Fruit
{
    protected static function name() : string
    {
        return "pear";
    }
}

不管怎样,从@ Rain的答案中,我可以看出为什么这是一个坏的实践,实际上并不是持续发展的最佳方向,所以我会考虑不同的策略来实现我想要达到的目标。我的好奇心终于满足了!谢谢大家的参与

所以在阅读了所有的答案后,我想出了一个解决办法,最终决定支持@chilliNUT的建议。我最后进行了如下工作:

abstract class Fruit
{
    protected abstract static function name() : string;

    /*
     * Basically, if you call the default method from any child (not necessarily a direct child) class, no problems,
     * but if you call it directly from the baseclass, you get the somewhat acceptable exception :)
     */
    public static function printName()
    {
        if(!is_subclass_of(static::class, self::class))
        {
            throw new \BadMethodCallException("Can't call base Fruit class methods directly!");
        }

        return "My name is: " . static::name();
    }
}

//those are abstract now, just to match the intention of them being utility singletons
abstract class Apple extends Fruit
{
    protected static function name() : string
    {
        return "apple";
    }
}

abstract class Pear extends Fruit
{
    protected static function name() : string
    {
        return "pear";
    }
}

不管怎样,从@ Rain的答案中,我可以看出为什么这是一个坏的实践,实际上并不是持续发展的最佳方向,所以我会考虑不同的策略来实现我想要达到的目标。我的好奇心终于满足了!谢谢大家的参与

谢谢你的回答!我也想到了这个场景,但对我来说,有两件事情似乎并不那么复杂和优化:-trait Printer可以包含在不一定包含静态名称方法的类中;-我将不得不添加使用打印机;对于每一个已经在扩展Fruit的类,这在某种程度上是一种代码复制形式,尽管它非常小,并且可以说已经足够好了。无论如何,谢谢你的建议,这可能确实是最好的选择,但我仍然感兴趣的是,是否有其他方法可以实现上述行为:为了回答您最初的问题:Fruit将其作为默认功能提供给其所有子类,这是必需的,因为它们实现了抽象静态函数name:string,这反过来又用于printName方法。我明白您的意思,尽管原则包括类型的对象,我的问题是相当静态的实现。我可以同意,这违反了利斯科夫原则。但是假设我想要100个水果子类,其中只有2个需要静态printName的不同实现。我仍然希望为他们提供一个默认的实现,但也能够覆盖它。或者这种欲望本身就是违反了利斯科夫原则
但是我实际上对静态实现更感兴趣,因为这些是我试图派生的实用程序类。非常感谢您的努力!谢谢你的回答!我也想到了这个场景,但对我来说,有两件事情似乎并不那么复杂和优化:-trait Printer可以包含在不一定包含静态名称方法的类中;-我将不得不添加使用打印机;对于每一个已经在扩展Fruit的类,这在某种程度上是一种代码复制形式,尽管它非常小,并且可以说已经足够好了。无论如何,谢谢你的建议,这可能确实是最好的选择,但我仍然感兴趣的是,是否有其他方法可以实现上述行为:为了回答您最初的问题:Fruit将其作为默认功能提供给其所有子类,这是必需的,因为它们实现了抽象静态函数name:string,这反过来又用于printName方法。我明白您的意思,尽管原则包括类型的对象,我的问题是相当静态的实现。我可以同意,这违反了利斯科夫原则。但是假设我想要100个水果子类,其中只有2个需要静态printName的不同实现。我仍然希望为他们提供一个默认的实现,但也能够覆盖它。或者这种愿望本身违反了Liskov原则?我看到了您的更新,但实际上我对静态实现更感兴趣,因为这些是我试图派生的实用程序类。非常感谢您的努力!这可能是一个很好的解决方法,您将它放在父类中一次并完成。我最后把苹果和梨都抽象了,因为它们是实用的单例,并在水果中实现了你的建议。你可以看到我对结论的回答。这可能是一个很好的解决办法,你把它放在父类中一次,然后就完成了。我最后把苹果和梨都抽象了,因为它们是实用的单例,并在水果中实现了你的建议。你可以看到我对结论的回答。不客气。很好的解决方案,但我认为您甚至不希望运行时进入方法的主体:驻留,您看,这是最接近于不进入的—它在进入后立即停止!:我的意思是,我不想执行不可预测的行为,也不想根据方法体以及方法体内部可能发生或可能不会发生的情况而出现不可预测的错误。欢迎您。很好的解决方案,但我认为您甚至不希望运行时进入方法的主体:驻留,您看,这是最接近于不进入的—它在进入后立即停止!:D整个要点是,我不想执行不可预测的行为,也不想根据方法体以及方法体内部可能发生或可能不会发生的情况而产生不可预测的错误。
public function printName()
{
    return "My name is: " . static::name();
}
$a = new Apple();
$p = new Pear();

echo $a->printName();
echo $p->printName();
abstract class Fruit
{
    protected abstract static function name() : string;

    /*
     * Basically, if you call the default method from any child (not necessarily a direct child) class, no problems,
     * but if you call it directly from the baseclass, you get the somewhat acceptable exception :)
     */
    public static function printName()
    {
        if(!is_subclass_of(static::class, self::class))
        {
            throw new \BadMethodCallException("Can't call base Fruit class methods directly!");
        }

        return "My name is: " . static::name();
    }
}

//those are abstract now, just to match the intention of them being utility singletons
abstract class Apple extends Fruit
{
    protected static function name() : string
    {
        return "apple";
    }
}

abstract class Pear extends Fruit
{
    protected static function name() : string
    {
        return "pear";
    }
}