few days ago i was on a job interview, i was asked a question like this one:
There is an abstract class A with two methods foo and bar, from
it generated derived class C, which was implement only the method
foo. What changes need to take place in the script, in order to make
it work, while the implementation and interface classes A and C
should not be changed
abstract class A {
abstract public function foo();
abstract public function bar();
}
class C extends A {
public function foo() {
// some code
}
}
i said: okay we can simple add one method to our C class
public function bar() {
//
}
they said this is ok, but what if you can't add this method and you can't change abstract class A (and its methods).
And there are two options, either my interviewer are fool or i am fool and missing something.
I have read php.net documentation about abstract classes and i do not see any other solution.(ofcourse i can make class A not abstract or remove abstract modifier from bar method but i am not allowed to do that);
Help me please, because this question don't let me sleep!
You Need to declare Class C is Abstract.
Related
Since I've just jumped from another language to PHP, I would like to ask you what would be a correct way of adding an extension to a class. My config right now is as follows:
class A extends B {
use C;
public function a(){
}
}
I need to add some additional functions to class A, but logically divide them from it, so I though I would be using a trait C.
So my question is - can I use function a() in my trait C? I know I can define abstract function a() in trait C, however I believe that wouldn't be a good practice at all. Maybe I can somehow inject this into a trait or is it a bad practice as well?
It is possible, the choice is a discretion of the developer, the best solution is based on experience.
trait C {
public function hello() {
parent::a();
echo 'World!';
}
}
class B {
function a() {
echo "hello";
}
}
class A extends B{
use C;
}
(new A())->hello(); // helloWorld!
Let's say:
Class B {
public function a () {
//Does something
}
}
Class A extends B {
//We got access to B's public function. If you want to execute B's a and add some more content, then
public function a() {
parent::a();
//Some more content
}
}
Traits were developed due to PHP's nature of not allowing to inherit from multiple classes (Single inheritance). By creating a trait and apply it to a class, you know inherit it's methods
http://php.net/manual/en/language.oop5.traits.php
It really comes down to your needs.
Q: Do you want to create an interface and make other classes implement certain methods?
A: Create an interface
Q: Do you want to create an abstract class with some implementations and allow other classes to use them? A: Create an abstract class
Q: Do you want a class to inherit from two other classes and they've got different functionalities? A: Create a trait
The best approach is to use the tools at your disposal in order to output your desired result and keeping it organized
Went over a thing like this and I don't know
abstract class Foo {
abstract private function test();
}
Is this a nonsense or NOT?
If not please explain why.
if you speak about private range inside you abstract class, no it is not a nonsence
Since an abstract class can contain functionality (as opposed to an interface) it can have private variables or methods.
I will give you this link with a great answer (even it is in java, it is the same with php) Why is there a private access modifier in an abstract class in Java, even though we cannot create an instance of an abstract class?
Abstract methods cannot be private, because by definition they must be implemented by a derived class. If you don't want it to be public, it needs to be protected, which means that it can be seen by derived classes, but nobody else.
The PHP manual on abstract classes shows you examples of using protected in this way.
http://php.net/manual/en/language.oop5.abstract.php
It makes sense if you want to make that method inaccessible further down in the inheritance chain, e.g. grandchildren of that abstract class. For example:
abstract class Foo {
abstract private function test();
}
class FooChild extends Foo {
private function test()
{
// Here you implement the body of the method
}
public function bar()
{
$this->test(); // This will work
// Do something else
}
}
class FooGrandChild extends FooChild {
}
$grandchild = new FooGrandChild();
$grandchild->test(); // This will throw an exception
I'm trying to write an abstract class (or interface) which forces the extending class to implement a protected static function.
But this is neither possible with an abstract class nor an interface.
Errors:
static functions should not be abstract
access type for interface members must be omitted
Any ideas how to accomplish that?
UPDATE
The purpose is basically to call the public function statically. This way the class does not need to be instanciated.
It is also not necessary to make _doSpecificStuff() callable from class-external code.
abstract class Foo
{
public static function doStuff()
{
[generic code]
static::_doSpecificStuff();
}
// sth like that would be nice to have:
abstract static protected function _doSpecificStuff();
}
From a theoretical as well as a practical standpoint, there's no real need to declare a static method abstract.
Abstract methods are there to have a child class fill in a blank. That's typically because the parent class (the original abstract class) does some generic operation, but can/must be adapted to certain specific situations and can thus force child classes to implement only this particular variable part in the otherwise generic algorithm. Abstract methods are supposed to be a blank spot within a larger algorithm.
A parent method would call implementations of its abstract methods without knowing or caring who implements them or how they're implemented:
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
Foo doesn't care who or what fills in the blank doSomethingSpecific, it just relies on it being there and its signature, which abstract enforces. The specific object which implements this method or how it implements it is variable. This is important and is at the core of the issue.
Declaring a static method abstract is pretty useless in this scenario. Any static method can just as well be implemented as a non-static method, so there's no use for it here. If the class itself is supposed to call the abstract method as part of a larger generic algorithm as described above, there's no need for a static method.
So the only scenario left for a static method is for a public static method which is callable from anywhere:
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
The thing is, since the abstract class Foo is not itself calling this function but this function is only called from external code, you're not really talking about a fill-in-the-blank method, you're talking about an interface. So, you should be using an interface instead.
But even there, since you have to type the specific class name in your source code, hardcoded, there's little point for an interface as well.
The point of declaring an interface or abstract method signature is that you want to fix the method signature so any code can call that particular method without caring what object it's calling it on in particular. But since you have to hardcode the class name, there's no variability in the object you're calling it on. If you type Baz::bar(), you know exactly what class you're calling what method on. Therefore there's little point in abstracting the interface/signature.
Compare:
interface FooInterface {
public function bar();
}
function baz(FooInterface $foo) {
$foo->bar();
}
The function baz can rely on its argument having a bar() method due to the interface declaration. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
The class Foo can rely on it having the doSomethingSpecific method. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
What exactly are you relying on or abstracting here? You can be pretty darn sure Baz will have the method bar() every time, because you're only ever calling it on the same hardcoded class. Nothing is variable here.
I am just learning php and I came across final method, it says it can prevent overriding of a method in the superclass by a subclass. I would like you to please give me some examples of this as the textbook am using didn't explain enough.
For example if you have a superclass let's say Foo. Containing a final method called : bar
class Foo
{
final public function bar()
{
//Do action A
}
}
Now we have a subclass, let's say called Foo2, which extends from Foo.
class Foo2 extends Foo
{
//This class will not be able to override the bar() function.
}
As the final keyword indicated that the function can not be overridden, "Action A" will alway be the stuff the function does, it can not be changed in the subclasses.
I've been searching for an answer all day, but I can't seem to find one. Sorry if I don't make much sense, I'm losing my mind over this.
Here's what I'm trying to do:
abstract class Parent {
abstract public function Test();
}
class Child1 extends Parent {
abstract public function Test() {
echo "Test!";
}
}
class Child2 extends Parent {
public function Test2() {
echo "Test2!";
$this->Test(); // Child1::Test();
}
}
Again, sorry if I'm not making much sense. I will try to explain more if you need me to.
It's not an OOP pattern, and not available in any OOP language that I kow of (except for introspection magic):
Child2 do not know anything (and does not have to) about Child1 class. they could be defined independently.
I think that at this point you should explain what your needs are. I guess we could help you ,with some design pattern.
You can't. What you're tryning to do has no sense in OOP. If you want to execute Test() from the first Child, you need to move the function in the parent.
EDIT: Well, I'm going to be more comprehensive:
You're trying to call a function of another child, which have only the parent class in common. Child1 and Child2 are as close as String and Integer can be in Java (or any other OOP language). Imagine that you called .upper() function on a int: it doesn't make sense.
There are several things wrong here:
Parent is a reserved word
Child1 contains an abstract method, so it can't contain a body.
Child2 extends Parent, but doesn't implement the Test() method.
As a result, none of this will instantiate. Child2() should probably extend Child1(),(or implement the Test() method itself). Correct these problems, fix any other errors that PHP might tell you about then this:
$p = new Child2();
$p->Test2();
Should give you this:
Test2!Test!
You are missing the concept of abstract classes and methods.
Abstract classes
Abstract classes are classes that define some basic behavior and cannot be instantiated. They are designed to be subclassed.
Abstract methods
These are methods that need to be implemented by the extending class. Like interfaces abstract methods define behavior without an implementation.
Your code
In your code you declared an abstract class with an abstract method.
abstract class Parent {
public abstract function Test();
}
When another class subclasses Parent it must implement the abstract method making it concrete.
class Child extends Parent {
public function Test() {
echo "Test!";
}
}
Accessing sibling method
A class or instance has no concept of a sibling. A class cannot know who subclasses its parent and access it in a static way.
The Test overrided function in Child1 should not be abstract (as you are defining it). To call the Test function of Child1 from the Test2 function of Child2 use:
Child1 foo = new Child1();
echo foo->Test();
Thing you can do only because it's been defined as public, not because Child1 and Child2 have any relationship.