The doubt is:
When defining a constant constructor in a subclass, it is necessary that the default constructor of the upper class is constant.
However, when the default constructor of the upper class is defined as constant, it is not necessary that the constructor of the inherited class be constant.
The codes below exemplifies the situation:
// Default constructor of the subclass defined as constant:
class Super_class {
Super_class();
}
class Sub_class extends Super_class {
const Sub_class() : super();
}
// Default constructor of the upper class defined as constant:
class Super_class {
const Super_class();
}
class Sub_class extends Super_class {
Sub_class() : super();
}
Could someone explain to me how this works?
Constructors are not inherited. A const base class constructor imposes no const requirements on its derived classes.
A const constructor means that the object must be constructible in a const context. One way of thinking about it is that the object must be constructible at compilation time; it does not depend on any runtime values. Consequently, a const constructor can depend only on other things that are const, including base class constructors.
If your subclass has a const constructor, then it is must call a super-class const constructor, otherwise it won't be able to perform compile-time constant evaluation of the entire construction. The const superclass constructor does not need to be the unnamed (sometimes mistakenly named "default") constructor. The superclass just have to have some constant generative constructor that you can call.
Example:
class SuperClass {
final int foo;
factory SuperClass() => const SuperClass._(0);
const SuperClass._(this.foo);
}
class Subclass {
final int bar;
const SubClass(int foo, this.bar) : super._(foo);
}
A subclass does not have to have a const constructor, even if the superclass does. The superclass itself can have non-constant constructors as well as constant constructors.
Related
https://dart.dev/guides/language/language-tour#extending-a-class
Argument types must be the same type as (or a supertype of) the
overridden method’s argument types. In the preceding example, the
contrast setter of SmartTelevision changes the argument type from int
to a supertype, num.
I was looking at the above explanation and wondering why the arguments of subtype member methods need to be defined more "widely"(generally) than the original class's one.
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Function_types
class AnimalShelter {
Animal getAnimalForAdoption() {
// ...
}
void putAnimal(Animal animal) {
//...
}
}
class CatShelter extends AnimalShelter {
//↓ Definitions that are desirable in the commentary
void putAnimal(Object animal) {
// ...
}
//↓Definitions that are not desirable in the commentary
void putAnimal(Cat animal) {
// ...
}
//I can't understand why this definition is risky.
//What specific problems can occur?
}
I think this wikipedia sample code is very easy to understand, so what kind of specific problem (fault) can occur if the argument of the member method of the subtype is defined as a more "narrower"(specific) type?
Even if it is explained in natural language, it will be abstract after all, so it would be very helpful if you could give me a complete working code and an explanation using it.
Let's consider an example where you have a class hierarchy:
Animal
/ \
Mammal Reptile
/ \
Dog Cat
with superclasses (wider types) above subclasses (narrower types).
Now suppose you have classes:
class Base {
void takeObject(Mammal mammal) {
// ...
}
Mammal returnObject() {
// ...
}
}
class Derived extends Base {
// ...
}
The public members of a class specify an interface: a contract to the callers. In this case, the Base class advertises a takeObject method that accepts any Mammal argument. Every instance of a Base class thus is expected to conform to this interface.
Following the Liskov substitution principle, because Derived extends Base, a Derived instance is a Base, and therefore it too must conform to that same Base class interface: its takeObject method also must accept any Mammal argument.
If Derived overrode takeObject to accept only Dog arguments:
class Derived extends Base {
#override
void takeObject(Dog mammal) { // ERROR
// ...
}
}
that would violate the contract from the Base class's interface. Derived's override of takeObject could be invoked with a Cat argument, which should be allowed according to the interface declared by Base. Since this is unsafe, Dart's static type system normally prevents you from doing that. (An exception is if you add the covariant keyword to disable type-safety and indicate that you personally guarantee that Derived.takeObject will never be called with any Mammals that aren't Dogs. If that claim is wrong, you will end up with a runtime error.)
Note that it'd be okay if Derived overrode takeObject to accept an Animal argument instead:
class Derived extends Base {
#override
void takeObject(Animal mammal) { // OK
// ...
}
}
because that would still conform to the contract of Base.takeObject: it's safe to call Derived.takeObject with any Mammal since all Mammals are also Animals.
Note that the behavior for return values is the opposite: it's okay for an overridden method to return a narrower type, but returning a wider type would violate the contract of the Base interface. For example:
class Derived extends Base {
#override
Dog returnObject() { // OK, a `Dog` is a `Mammal`, as required by `Base`
// ...
}
}
but:
class Derived extends Base {
#override
Animal returnObject() { // ERROR: Could return a `Reptile`, which is not a `Mammal`
// ...
}
}
void main(){
Animal a1 = Animal();
Cat c1 = Cat();
Dog d1 = Dog();
AnimalCage ac1 = AnimalCage();
CatCage cc1 = CatCage();
AnimalCage ac2 = CatCage();
ac2.setAnimal(d1);
//cc1.setAnimal(d1);
}
class AnimalCage{
Animal? _animal;
void setAnimal(Animal animal){
print('animals setter');
_animal = animal;
}
}
class CatCage extends AnimalCage{
Cat? _cat;
#override
void setAnimal(covariant Cat animal){
print('cats setter');
_cat = animal;
/*
if(animal is Cat){
_cat = animal;
}else{
print('$animal is not Cat!');
}
*/
}
}
class Animal {}
class Cat extends Animal{}
class Dog extends Animal{}
Unhandled Exception: type 'Dog' is not a subtype of type 'Cat' of 'animal'
In the above code, even if the setAnimal method receives a Dog instance, a compile error does not occur and a runtime error occurs, so making the parameter the same type as the superclass's one and checking the type inside the method is necessary.
I saw simple class which was look like:
class SomeClass extends Object{
int a;
int b;
...
...
}
Why this class was extended an Object class? As in documentation was written "Because Object is the root of the Dart class hierarchy, every other Dart class is a subclass of Object." in https://api.dartlang.org/stable/2.4.0/dart-core/Object-class.html.
What will happened if we will not extends Object? Or maybe it will be useful in some specific problems?
All dart classes implicitly extend Object, even if not specified.
This can be verified using the following code:
class Foo {}
void main() {
var foo = Foo();
print(foo is Object); // true
}
Even null implements Object, which allows doing:
null.toString()
null.hashCode
null == something
Type 1:
class TestExample {
object Bell {
fun add(){
}
}
Class B{
TestExample.Bell.add()
}
Type 2:
class TestExample {
companion object Bell {
fun add(){
}
}
Class B{
TestExample.add()
}
In this type 1 and type 2, which is static example and which is singleton example? Both behaves similar behavior right?
From official Kotlin docs:
Object declarations
If you need a singleton - a class that only has got one instance - you
can declare the class in the usual way, but use the object keyword
instead of class
Companion objects
If you need a function or a property to be tied to a class rather than
to instances of it (similar to #staticmethod in Python), you can
declare it inside a companion object
I have two classes Class A and Class SRD (Sample classes for understanding the problem. Real classes are different). Both classes have same Function(method1) with same arguments. Both are not derived from different Classes.
Class SRD is the member of Class A. a function in Class A creates a new object for SRD and calls method1(). It should call the mock function. but it calls the actual implementation
I have Written mock classes for both the classes and defined the mock method in both the classes and Wrote EXPECT_CALL in TEST function
class A{
private:
SRD* srd;
public :
bool Method1();
bool MethodX();
SRD* getsrd() {return srd;}
};
bool A :: MethodX()
{
srd.Method1(); // Not Calling Mock Method - Calling Actual
//Implementation
}
bool A::Method1()
{
....
}
class SRD{
public:
bool Method1();
};
class MockSRD : public SRD{
MOCK_METHOD0(Method1, bool())
};
class MockA : public MockA{
MOCK_METHOD0(Method1, bool())
};
bool SRD::Method1()
{
....
}
class TestA : public A {};
TEST_F(TestA, test1)
{
MockSRD srd;
EXPECT_CALL(srd, Method1())
.Times(testing::AnyNumber())
.WillRepeatedly(Return(true));
srd.Method1() //Working fine - Caling mock Method;
MethodX()
}
When i call s1.Method1(), It should call the mock method. how should i do that ?
I don't want to change the production code.
Thanks for taking time to respond the Question . #Chris Oslen & #sklott
I forgot to make the base class method to Virtual. Its worked fine when i change the base class methods
In the following example, interface IFoo declares a function signature requiring two number arguments. Abstract class BaseFoo implements this interface, but declares the function with a different signature. Finally, concrete class Foo extends BaseFoo and implements BaseFoo's version of the function declaration.
interface IFoo {
func(x: number ): number
}
abstract class BaseFoo implements IFoo {
abstract func(x: number): number
}
class Foo extends BaseFoo {
func() { return -1 } // Does not match interface func declaration
}
let foo: IFoo = new Foo() // Should not be able to instantiate a Foo as an IFoo
let y = foo.func() // Should not be able to call without an argument
console.log(y)
This contrived example illustrates something that happened in real life: I had an existing interface in a codebase. I updated one of it's function's signatures, with the expectation that the compiler would help me find all the classes who would need to be updated. But, no errors.
Why am I allowed to instantiate an abstract class with a function signature that doesn't match the interface?