You cannot answer this question unambiguously. Different OOP languages implement OOP paradigm differently.
In Ruby you will get only "Hi, I am bird!"
class Animal
def initialize
puts "Hi, I am animal!"
end
end
class Bird < Animal
def initialize
puts "Hi, I am bird!"
end
end
class Pigeon < Bird
def initialize
super # <= call to the superclass
end
end
pg = Pigeon.new
In PHP we get only "Hi, I am bird!"
<?php
class Animal {
public function __construct()
{
echo "I'm Animal";
}
}
class Bird extends Animal {
public function __construct()
{
echo "I'm Bird";
}
}
class Pigeon extends Bird {
public function __construct()
{
parent::__construct();
}
}
$Pigeon = new Pigeon();
?>
While in C++ you will get both "Hi I am animal!" and "Hi I am Bird!"
#include <iostream>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Hi I am animal!" << endl;
}
};
class Bird : public Animal
{
public:
Bird()
{
cout << "Hi I am Bird!" << endl;
}
};
class Pigeon : public Bird
{
public:
Pigeon():Bird(){} // <= call to the base constructor
};
int main()
{
Pigeon pg;
}
In Swift (Apple) we get both, too
class Animal {
public init() {
print("I'm Animal")
}
}
class Bird: Animal {
public override init() {
print("I'm Bird")
}
}
class Pigeon: Bird {
public override init() {
super.init()
}
}
var pigeon = Pigeon()
To understand why, you should get into details of how C++ implements OOP (vtables and etc.) and how Ruby classes lookup its methods and constants in the hierarchy, and other languages.
In addition if you want to see Object Oriented "Nightmare" then have a look at Lua, though I like it.
As to your question in the title: "Are grandparent classes also parents",
of course subclasses are related to all super-classes up in the hierarchy chain, but that relationship are implemented differently in different programming languages.
Animal
a "parent" for both? This has a general answer in the OOP world. b) Which constructors get called? This may depend on the specific language/compiler. $\endgroup$