Inheritance, does the "is a" relationship always have to hold? - oop

If class B inherits from class A, does class B always have to be a sub-type of A when used in inheritance?
I am thinking if it is possible to use inheritance to provide extra code to B, when B is not a subtype of A?

If type A inherits from B, that means two things:
Class `A` will be able to use public and protected static methods from class `B`, without having to specify the class name, and objects of class `A` will implicitly include all public and protected class members from `B` without having to respecify them.
Any code accepting objects of type `B` will, at at compile time, accept objects of type `A`, and objects of class `A` will be able to use class `B`'s public and protected instance methods on themselves.
Interfaces essentially embody concept #2 but not #1 (since interfaces have no static methods, and have no members that can be used implicitly without having to specify them). There is no built-in way to achieve #1 without #2; the only significant benefit of having #1 without #2 would be to save typing.

If:
class B extends A
Than B is by definition a subtype of A.
If you don't want that, you can use PHP's traits, which is basically interfaces with implementation.

Related

How to extend derived classes by defining class(es) that exposes the instance as a property

I have a class that I would like to extend by defining a new class that contains the first class as a public property, as well as additional added properties. However, the class that I'm extending has multiple derived types, which should be treated the same in the extension class.
Below is an example of what I am trying to do:
Public Class ClassA
End Class
Public Class ClassB
Inherits ClassA
End Class
Public Class ClassC
Inherits ClassA
End Class
Public Class BaseExtended
Public Property Foo As ClassA
Public Property ExtendedMetaData1 As Double
Public Property ExtendedMetaData12 As Integer
End Class
Public Class DerivedExtendedB
Inherits BaseExtended
Public Property Foo As ClassB
End Class
Public Class DerivedExtendedC
Inherits BaseExtended
Public Property Foo As ClassC
End Class
The code that uses an instance of any of the 'extended' classes would then need use that instance appropriately depending on it's type. There would be many cases where the property 'Foo' needs to be accessed and modified outside of the class that it belongs to.
If I were to implement something like what I have shown above, that would require that I first cast it to the required type before accessing or modifying it. Ideally I would like to do that inside the 'DerivedExtended' class; The alternative, I think, would be to duplicate code to cast that property would [hundreds of times] in the client code.
Private Sub ClientUsesObject(bar As BaseExtended)
' Perform a task that is agnostic Foo type
' Would not require that Foo be cast to any specific type
If bar.GetType() Is GetType(DerivedExtendedB) Then
Dim barCast As DerivedExtendedB = DirectCast(bar, DerivedExtendedB)
' Perform task that requires Foo to be of type ClassB
ElseIf bar.GetType() Is GetType(DerivedExtendedC) Then
Dim barCast As DerivedExtendedC = DirectCast(bar, DerivedExtendedC)
' Perform task that requires Foo to be of type ClassC
End If
End Sub
What I'm looking for is advice outlining or describing a design pattern that can handle this situation. I've searched for quite a while, and have not been able to find any examples that solve this problem.
I realize that this may be somewhat of an "XY" problem. I'm working with existing code that simply assumes all instances are of the same derived type (when in fact some instances are of the other derived type). As such, the existing code does not work. To me what I've tried to outline above seems like the most straightforward path, but I'm open to alternative if this is just the wrong approach.
This pattern of type covariance in derived classes is the canonical reason for what is called in C++ the "Curiously Recurring Template Pattern" and has been called in .NET the "Curiously Recurring Generic Pattern." I believe it's also sometimes referred to as "F-Bounded Polymorphism" (not a computer scientist, so I might have the reference wrong).
You can write a base class like this:
Public Class Base(Of TDerived As Base)
Public Overridable Property foo As TDerived
End Class
And then use it like this:
Public Class MyDerived
Inherits Base(Of MyDerived)
End Class
Then, the derived class has a property foo whose type is MyDerived. No casting required by clients.
However, this has some limitations. It works best when you don't need to switch back and forth between derived and base. There is no one Base, so you can't declare instances of it. If you want to be able to declare something as Base, then you end up needing to fall back on a non-generic base class. This will still work well for certain usage patterns where you don't need to convert from base to derived, but otherwise you run right back into the casting problems you are trying to avoid.
Eric Lippert has written a bit about this pattern. He's always interesting to read, so I'd recommend looking up his commentary.
Another alternative to consider, if the generic approach doesn't work for you, is code generation. You can use T4 templates to process a compact description of what your code should be, and generate the code files from them. A long list of casts is less tedious if you only write the machinery to generate it, you don't write them all out explicitly.

Should I use data class even if I implement all of hashCode(), equals() and toString()?

I have a class which is the parse result of a string, so I have to enforce the toString() to return that source string instead of those parsed values. It also has custom equals()/hashCode() mechanism. Is there any benefit to still mark it as a data class?
The auto-generated parts of data classes are:
The compiler automatically derives the following members from all
properties declared in the primary constructor:
- equals()/hashCode() pair,
- toString() of the form "User(name=John, age=42)",
- componentN() functions corresponding to the properties in their order of declaration,
- copy() function.
If any of these functions is explicitly defined in the class body or
inherited from the base types, it will not be generated.
The componentN() function enables destructuring like for ((a, b, c) in dataClass) { ... }
However, data classes CANNOT be inherited. (You can define a data class that extends another non-data class though.)
If you think that it is possible that some classes extend your class, then do not make it a data class.
If you think that no class will extend your class in the future, and you maybe need the destruction or copy() function, then make it a data class.

Why parent class is not able to access child class member

If we go according to below code
class A;
int a = 10;
endclass
class B extends A;
int b = 20;
endclass
program test;
A a1;
B b1;
initial begin
b1 = new();
a1 = b1; //child class object is assigned to parent class handle
$display("Value of variable b is %x", a1.b);
end
endprogram
Then the above code results into error that "Could not find member 'b' in class 'A'"
Now my observation is that when extended class object is assigned to base class handle then simulator will check the type of handle and check whether variable is present in that class or not. As variable b is not defined in base class then it will result into error.
So I want to confirm whether my above observation is correct or incorrect?
I would welcome if anyone wants to add something to my observation, in case it's correct.
Thanks
You are correct, and it is the intended behavior in OOP languages I know (I don't especially know the one you are using, but your example is simple enough). Being able to use a variable declared by a child class would result in a violation of the object oriented principle of polymorphism (or subtyping).
I will answer you in Java, because I'm sure of the syntax in this language for the example i want to give. Imagine two variables with the same declared type :
public A buildA () {
return new B();
}
public static void main () {
A a1 = new A();
A b1 = buildA();
}
The polymorphism principle is that a1 and b1 should implement the same interface and be used indifferently. If I was allowed to access a variable's member b, since the compiler couldn't guess which is base and which is child, then it would allow the program to crash at runtime every time I access a concrete A, removing the safety net types are supposed to provide.
I would not use the terms parent and child class here. It implies you have two separate class objects.
What you describe is two different class types where one type is derived/extended from a base type. Then you declare two class variables: a1 and b1. These variables may hold a handle to class object of the same type, or a handle to an object of any type extended the type of the variable. However, the compiler will not let you reference any variable or member that has not been defined by type of the class variable regardless of the type of the object the class variable currently hold a handle to.
OOP gives you the ability to interact with a class variable with the possibility of it having a handle to much more complex object without you knowing what extensions have been made to that object. But you have to assume that the object could be the same type as the class variable. The compiler enforces this as well. If you want to interact with the extended class variables, you need to use an extended class variable type.

When can a reference's type differ from the type of its object?

Yesterday I was asked a question in an interview:
Suppose class A is a base class, and class B is derived class.
Is it possible to create object of:
class B = new class A?
class A = new class B?
If yes, then what happen?
Objects of type B are guaranteed to also be objects of type A. This type of relationship is called "Is-a," or inheritance, and in OOP it's a standard way of getting polymorphism. For example, if objects of type A have a method foo(), objects of type B must also provide it, but its behavior is allowed to differ.
The reverse is not necessarily true: an object of type A (the base class) won't always be an object of type B (the derived class). Even if it is, this can't be guaranteed at compile-time, so what happens for your first line is that the code will fail to compile.
What the second line does depends on the language, but generally
Using a reference with the base type will restrict you to only accessing only members which the base type is guaranteed to have.
In Java, if member names are "hidden" (A.x exists and so does B.x, but they have different values), when you try to access the member you will get the value which corresponds to the type of the reference rather than the type of the object.
The code in your second example is standard practice when you are more interested in an API than its implementation, and want to make your code as generic as possible. For instance, often in Java one writes things like List<Integer> list = new ArrayList<Integer>(). If you decide to use a linked list implementation later, you will not have to change any code which uses list.
Take a look at this related question: What does Base b2 = new Child(); signify?
Normally, automatic conversions are allowed down the hierarchy, but not up. That is, you can automatically convert a derived class to its base class, but not the reverse. So only your second example is possible. class A = new class B should be ok since the derived class B can be converted to the base class A. But class B = new class A will not work automatically, but may be implemented by supplying an explicit conversion (overloading the constructor).
A is super class and B is a SubClass/Derived Class
the Statement
class A = new class B is always possible and it is called Upcasting because you are going Up in terms of more specific to more General
Example:
Fruit class is a Base Class and Apple Class is Derived
we can that Apple is more specific and must possess all the quality of an Fruit
so you can always do UPcasting where as
DownCasting is not always possible because Apple a=new Fruit();
A fruit can be a Apple or may it is not

Why can't I cast a generic parameter with type constraint to the constrained type?

I am getting used to using interfaces, generics and develping them using inheritance in a real envrionment whilst trying use and implement this into a new architecture for one of our upcoming projects and I have a question regarding generics which I am confused about.
This is more of a educational question for myself because I can't understand why .NET doesn't allow this.
If I have a generic class which is (Of T As IA, T2 As A) then I have the following interfaces and class which implements the base interface
Public Interface IA
Property A As String
End Interface
Public Interface IB
inherits IA
Property B As String
End Interface
Public Class GenericClass(Of T As IA, T2 As A)
'Should be list of IA?
Public list As New List(Of T)
Public Sub Add()
End Sub
End Class
Because I have made T as IA why in the add method is Dim foo4 As T = New A() not legal when
Dim foo1 As IA = New A()
Dim foo2 As T
Dim foo3 = Activator.CreateInstance(Of T2)()
Dim x As IA = foo2
Dim y As IA = foo3
list.Add(x)
list.Add(y)
All of the above is? This is becoming a learning curve for me with generics etc. but I am just very confused with why I logically can't do this?
EDIT: Sorry forgot Class A and error message please see below
Public Class A
Implements IA
Public Property A As String Implements IA.A
End Class
EDIT 2: Error was typed incorrectly
"Value of type class a cannnot be converted to T"
It's not exactly clear what you're trying to do, but one problem I notice is that you seem to be assuming that a List<TypeThatImplementsIA> is somehow interchangeable with a List<IA>. That is not the case. Imagine that A were a class of flying birds, and IA were implemented by creatures that can fly, and someone created a GenericClass<Airplane, BlueJay). Even though Airplane and BlueJay are both things that can fly, one would not be able to add a BlueJay to a List<Airplane>. The one common situation in the Framework where one can use a GenericType<DerivedType> as a GenericType<BaseType> is with IEnumerable<T>. The reason for that is that one can't store T's into an IEnumerable<T>--one can only read them out. If one is expecting an IEnumerable<Animal> and one is given an IEnumerable<MaineCoonCat>, then every time one expects to read an Animal, one will read an instance of MainCoonCat, which inherits from Animal and may thus substitute for it. This feature of IEnumerable<T> is called covariance.
There's a limitation to such behavior, though, which stems from the fact that there is a difference between using an interface as a type of storage location (variable, parameter, etc.), versus using it as a constraint. For every non-nullable value type, there are actually two related types within the Runtime. One of them is a real value type, which has no concept of inheritance (but can implement interfaces). The other is a heap-object type which derives from ValueType (which in turn derives from Object). Most .net languages will implicitly convert the former type to the latter, and allow code to explicitly convert the latter to the former. Interface-type storage locations can only hold references to heap objects. This is significant because it means that while a struct which implements an interface is convertible to that interface type, that doesn't mean instance of the struct is an instance of that interface type. Covariance works on the premise that every object returned by e.g. an IEnumerable<DerivedType> may be used directly as an instance of BaseType without conversion. Such direct substitutability works with inherited class types, and with interfaces that are implemented by class types. It does not work with interfaces implemented by struct types, or with generics that do not have a class constraint. Adding a class constraint to a generic class type parameter will allow that type parameter to participate in covariance, but may preclude the use of structs as the generic type parameter. Note that unless one has particular reason to expect that an interface will be implemented by structures (as is the case with e.g. IComparable<T>, in many cases it's unlikely that an interface would be implemented by a structure and thus a classconstraint would be harmless).
That's because T is not the interface IA itself. It is one implementation of it.
Suppose that you have another class that implements IA:
Public Class B
Implements IA
Public Property B_A As String Implements IA.A
Public Property OtherProperty as Object
End Class
Then you create a new instance of Generic Class like this:
Dim genericObject as new GenericClass(Of B, A)
So in this case, T now is B, and A cannot be casted to B.
In this case instead, replacing the part of your doubt, a code that would make sense for me:
Dim foo4 As IA = New T()
EDIT due to comment
To be able to instantiate T, it is necessary to declare the New constraint in the type definition. So the generic class declaration would be:
Public Class GenericClass(Of T As {New, IA}, T2 As A)