2013-02-08 3 views
0

У меня есть родительский класс, который имеет открытую публичную функцию. Можно ли запретить доступ к этому методу в производном классе? Другие классы, которые вытекают из родительского класса, должны все еще иметь возможность называть его.Запретить вызов конечной родительской функции в php

class ParentClass { 
    final public function test() { 

    } 
} 
class ChildClass extends ParentClass { 

} 
class ChildClass2 extends ParentClass { 

} 

$child = new ChildClass(); 
$child2 = new ChildClass2(); 
// make this illegal: 
$child->test(); 
// but not this: 
$child2->test(); 
+1

сделать его приватным – Ibu

+0

@Ibu: Я не хочу запрещать вызов этого метода во всех производных классах. Я хочу запретить его в одном конкретном экземпляре, где вызов этого метода не имеет никакого смысла и приведет к нежелательному поведению. Другие производные классы должны иметь возможность вызвать функцию. – DudeOnRock

+0

Просто используйте личное ключевое слово –

ответ

3

Когда вы унаследовали от класса это означает, что производный класс is a класс, который наследуется. Это означает, что он имеет ту же базовую функциональность, которая может быть расширена, переопределена и так далее. Если нет никакого смысла, чтобы производный класс имел метод, который определен в родительском классе, означает, что производный класс не является классом, который он получает.

Для реального мира, например, скажем, у вас есть класс FlyingMachine, который имеет метод Fly и Move, это не было бы логично, если бы вы производный класс Car из FlyingMachine, потому что машины не летают, при выводе класса AirPlane из упомянутого базового класса совершенно хорошо. Но было бы логично, если бы у вас был базовый класс Machine, у которого был метод Move, и автомобиль был получен из этого класса Car : Machine (автомобиль - машина, справа?), FlyingMachine - машина тоже, поэтому FlyingMachine : Machine - это прекрасно, и поскольку воздушный самолет является летающая машина AirPlane : FlyingMachine имеет смысл.

Для вашего данного примера это должно быть что-то вроде:

abstract class VeryBaseClass { 
    public function MethodThatIsLogicalForEveryDerivedClass() {} 
} 

abstract class BaseClass extends VeryBaseClass { 
    public function SomeOtherFunctionThatMakesSenseOnlyForSomeClasses() {} 
} 

class ClassThatShouldNotHaveSpecificFunctionDefinedInBaseClass extends VeryBaseClass{} 

class ClassThatShouldHaveSomeOtherMethod extends BaseClass {} 

Edit:

Если есть функциональность, что некоторые производные классы нужно, но для некоторых из них это должно быть публичным, и для некоторых из них нет. Вы должны определить в базовом классе этот метод как защищенный (производный класс может получить доступ к одному, но извне невозможно). И в производном классе, которые требуют, чтобы этот метод был общедоступным, выдает другой метод и вызывает метод родителя. Например:

abstract class Car { protected function Shift() {} } 

class ManualCar extends Car { 
    public function Shift() { parent::Shift(); } 
} 

class AutomaticCar extends Car { 
     //Some implementation of automatic car that uses protected Shift method 
} 

Little demo

+1

Допустим, класс Car имеет метод shift(). Теперь я получаю класс AutomaticCar и класс ManualCar. Я знаю, что мог бы сделать метод shift() только частью класса ManualCar, но автоматические автомобили тоже должны сдвигаться. Это не водитель, которому приходится иметь дело с этим.Метод, который у меня есть, вызывается другими функциями внутри класса (скажем, бортовой компьютер может сдвигаться), но было бы плохо, если водитель автомобиля попытается сдвинуться. Не существует ли языковой конструкции, которая позволила бы мне «скрыть» вариант переключения с водителя автомата? – DudeOnRock

+0

@DudeOnRock Вы можете достичь этого с помощью модификаторов доступа. Я отредактирую свой ответ. – Leri

+0

С вашим редактированием функция больше не является окончательной, и я надеялся сохранить ее. – DudeOnRock

1

Как насчет проверки этого класса в методе, и бросать исключение, если это запрещено класс:

class ParentClass { 
    final public function test() { 
     if (get_class($this) == "ChildClass") 
      throw new Exception("ChildClass cannot call test()") 
    } 
} 

NB: это довольно злой

+1

Если у меня было 100 классов, которые не должны иметь метод 'test'? Мне лучше убить себя, чем использовать это. : D Это действительно зло и грязно. ;) – Leri

+0

Зло, но я думаю, это решит мою проблему. Не в очень инкапсулированном виде, но то, что я имею прямо сейчас, также не является идеальным. – DudeOnRock

+0

Если у вас есть 100 классов, которые не должны иметь его, тогда вам лучше всего реорганизовать все. Но ... если все работает, и это всего лишь один класс, а test() вызывает некоторую труднодоступную прерывистую ошибку при вызове ChildClass, и вы просто хотите удостовериться, что никакой будущий программист не делает этого ... тогда может быть, немного зла в порядке. –

Смежные вопросы