I would like to run unit tests from the abstract class instead of from the concrete classes that inherit from it. I tried a few things that would not compile:
unittest(this T) { ... }
abstract class Parent(this T) : GrandParent
{
...
unittest
{
T x = new T();
x.something = true;
assert(x.something == true);
}
...
}
Is there something else I can do to de-duplicate the thousands of lines of unit tests that are otherwise going to exist for each child class?
If you're happy with a base class that's specialized (and thus duplicated) for each subclass:
abstract class Base(T) {
static assert(is(T : typeof(this)), "Tried to instantiate "~typeof(this).stringof~" with type parameter "~T.stringof);
unittest {
import std.stdio : writeln;
auto a = new T();
writeln(a.s);
}
}
class Derived : Base!Derived {
string s() {
return "a";
}
}
Instead of the static assert, I'd have preferred to have a template constraint on Base, but sadly this doesn't work (when the constraint is tested, we don't yet know if Derived inherits from Base!Derived, since that only happens after the constraint has passed, of course).
This pattern is known in C++ as Curiously Recurring Template Pattern (CRTP).
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.
For example in Java I could write:
public abstract class Element<S extends Snapshot> { ... }
public abstract class Snapshot<E extends Element> { ... }
And then, somewhere, extend this classes:
public class SnapshotImpl extends Snapshot<ElementImpl> { ... }
public class ElementImpl extends Element<SnapshotImpl> { ... }
But when I tried to implement same class hierarchy in Kotlin:
abstract class Element<S : Snapshot>
abstract class Snapshot<E : Element>
I got following compilation errors:
Error:(6, 28) Kotlin: One type argument expected for class Snapshot<E> defined in model
Error:(6, 25) Kotlin: One type argument expected for class Element<S> defined in model
Is there any way to reproduce same type parameter restrictions in Kotlin?
Kotlin doesn't have raw types, you cannot just drop the type parameters.
One option similar to raw types is to use star projections:
abstract class Element<S : Snapshot<*>> { /* ... */ }
abstract class Snapshot<E : Element<*>> { /* ... */ }
But you won't be able to normally work with the type parameters generic members.
Another option is to introduce mutual constraints like this:
abstract class Element<E : Element<E, S>, S : Snapshot<S, E>>() { /* ... */ }
abstract class Snapshot<S : Snapshot<S, E>, E : Element<E, S>>() { /* ... */ }
With this definition, you can be sure that if you define SomeSnapshot: Snapshot<SomeSnapshot, SomeElement>, the type SomeElement is aware of SomeSnapshot, because it is constrained to be derived from Element<SomeElement, SomeSnapshot>.
Then the implementation would be:
class SomeElement : Element<SomeElement, SomeSnapshot>() { /* ... */ }
class SomeSnapshot : Snapshot<SomeSnapshot, SomeElement>() { /* ... */ }
I recently came across this issue when designing one of the abstract layers of my app.
First of the options in hotkey's answer fails to compile with "This type parameter violates the Finite Bound Restriction" (at least with newer Kotlin 1.2.71). The second one works, but can be optimized a bit. Even thought it is still bloated it makes a difference, especially when you have more type parameters. Here is the code:
abstract class Element<S : Snapshot<*, *>> { /* ... */ }
abstract class Snapshot<E : Element<S>, S : Snapshot<E, S>> { /* ... */ }
I have Sealed Class like below.
sealed class Number {
object One: Number() {
}
object Two: Number() {
}
object Three: Number() {
}
object Four: Number() {
}
}
then, I want to use One, and Two using sealedSubclasses.
// this code compile error. `Operator '==' cannot be applied to 'KClass<out KClass<out Number>>' and 'Number.One'`
val subClasses = Number::class.sealedSubclasses.filter { clazz -> clazz::class == Number.One }
Can I solve this? Do you know any Idea?
Use clazz == Number.One::class.
Currently, you’re using clazz::class which is KClass<out KClass<out Number>>, the class of what was already a class.
And you forgot the ::class at the end.
However, you’re filtering to find out which subclass is the class you already know so there’s no point. You could just replace you’re whole line of code with val subclasses = listOf(Number.One::class).
This question already has answers here:
Kotlin calling non final function in constructor works
(3 answers)
Closed 1 year ago.
I have a (more complex) version of these 4 classes the problem is when I try to initialize Test() android studio tells me cannot call data.log() on a null object reference. Why is this? how can i fix it?
abstract class Test() {
protected abstract val data: CustomClass
init {
data.log()
}
}
class myClass(): Test() {
override val data = Hello()
}
abstract class CustomClass() {
function log() {
Log.i("TEST", "HELLO");
}
}
class Hello(): CustomClass() {
}
I have a lot of classes that extend Test() and Hello() I do not want to have to call data.log() in multiple classes to avoid repeating code
Try to evaluate your code step by step:
invoke myClass() -> myClass constructor called from your code
invoke Test() -> parent constructor called from myClass constructor
invoke Test's init -> init section called from Test constructor
NPE -> data field is not initialized yet
As you can see, the init section is called BEFORE the data is initialized. Solution to your problem is pretty simple, move the data field right into the Test's constructor and remove the abstract modifier:
abstract class Test(protected val data: CustomClass) {
init {
data.log()
}
}
class myClass(): Test(Hello())
P.S.: I hope this is just an example and you don't start your class names with lowercase. :)
I'm wondering if it is possible to design, for example, a type-safe singly linked list structure such that it is impossible to ask for the next node from the tail node.
At the same time, the client would need to be able to traverse (recursively or otherwise) through the list via node.getChild() but be prevented at compile time (at least with human-written explicit type checking) from going past the tail.
I'm wondering:
Is there a name for this type of problem?
Is there an object oriented or other approach that would help to avoid explicit run-time type checking?
The implementation language isn't important, but here's a Java example of what I'm thinking of.
Edit after Joop's answer:
public class TestHiddenInterfaces {
interface Node { HasNoChildNode getTail(); }
interface HasNoChildNode extends Node {};
interface HasChildNode extends Node { Node getChild(); }
class HasNoChild implements HasNoChildNode {
#Override public HasNoChildNode getTail() { return this; }
}
class HasChild implements HasChildNode {
final Node child;
#Override
public Node getChild() { return child; }
HasChild(Node child) {
this.child = child;
}
#Override public HasNoChildNode getTail() {
if(child instanceof HasChild) return ((HasChild) child).getTail();
else if(child instanceof HasNoChild) return (HasNoChildNode) child;
else throw new RuntimeException("Unknown type");
}
}
#Test
public void test() {
HasNoChild tail = new HasNoChild();
assertEquals(tail, tail.getTail());
HasChild level1 = new HasChild(tail);
assertEquals(tail, level1.getTail());
HasChild level2 = new HasChild(level1);
assertEquals(tail, level2.getTail());
}
}
In Scala one uses "case types" for such typing. In Java, or UML diagrams, one often sees that a distinction is made between branch and leaf. And that can reduce half the memory of unused leaf children.
The types coexist like enum values.
So one might use the following:
/**
* Base of all nodes. For the remaining types I have dropped the type parameter T.
*/
public interface Node<T> {
void setValue(T value);
T getValue();
}
public interface HasParent extends Node {
void setParent(HasChildren node);
HasChildren getParent();
}
public interface HasChildren extends Node {
void setChildren(HasParent... children);
HasPOarent[] getChildren();
}
public final class RootBranch implements HasChildren {
...
}
public final class SubBranch implements HasChildren, HasParent {
...
}
public final class Leaf implements HasParent {
...
}
public final class RootLeaf implements Node {
...
}
The usage would either use overloading, or distinguishing cases:
void f(Node node) {
if (node instanceof HasParent) {
HasParent nodeHavingParent = (HasParent) node;
...
}
}
Personally I think this is overdone in Java, but in Scala for instance, where the type declaration is the constructor, this would make sense: SubBranche(parent, child1, child2).
The only way that such a hierarchy could exist is if each level implemented a different interface (where I'm using interface in a wider sense than a specific language term).
The root node cannot implement getParent - that's the only way you'll achieve a compilation error that I can think of. So, the "interface" of the root node doesn't include getParent.
The first children can implement getParent - but in order to be compile safe, they have to return a type that is, at compile time, known to be the root node (i.e. a type that doesn't implement getParent).
At the next level, the implementation of getParent must return a type that implements a getParent that returns a root node that doesn't have getParent.
In short, even if you did choose to produce such an implementation, it would be very brittle, because you'd need to write different code to deal with each level of the hierarchy.
There are certain problems where a runtime check is right, and this would be one of those times. If every problem could be solved at compile time, then every compiled program would just be a set of results (and possibly a massive switch statement to pick which result you want to output)