Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use sealed classes with generics?

I have a parent abstract class and child classes which take generics.

public abstract sealed class Parent<T> permits ChildA, ChildB {}

public non-sealed class ChildA<T extends FileTypeA> extends Parent{}

public non-sealed class ChildB<T extends FileTypeB> extends Parent{}

In the parent class, I am getting warnings:

ChildA is a raw type. References to generic type ChildA<T> 
       should be parameterized

ChildB is a raw type. References to generic type ChildB<T> 
       should be parameterized

In the child classes, I am getting warnings:

Parent is a raw type. References to generic type Parent<T> 
       should be parameterized

Making them parameterized like this:

public abstract sealed class Parent<T> 
    permits ChildA<T extends FileTypeA>, ChildB<T extends FileTypeB> {}

Or even

public abstract sealed class Parent<T> 
    permits ChildA<T>, ChildB<T> {}

Gives the error:

Bound mismatch: The type T is not a valid substitute for the 
    bounded parameter <T extends FileTypeA> of the type ChildA<T>

How to remove these warnings and errors?

like image 993
khateeb Avatar asked Oct 08 '21 06:10

khateeb


People also ask

When would you use a sealed class?

Sealed Classes allow us to fix type hierarchies and forbid developers from creating new subclasses. They are useful when we have a very strict inheritance hierarchy, with a specific set of possible subclasses and no others.

Can we override sealed class?

You can't inherit from a sealed class, so no inheritance, no override. The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event. When applied to a class, the sealed modifier prevents other classes from inheriting from it.

Can I instantiate a sealed class?

Sealed classes cannot be instantiated directly. Sealed classes cannot have public constructors (The constructors are private by default). Sealed classes can have subclasses, but they must either be in the same file or nested inside of the sealed class declaration.

Can sealed classes inherit?

A sealed class, in C#, is a class that cannot be inherited by any class but can be instantiated. The design intent of a sealed class is to indicate that the class is specialized and there is no need to extend it to provide any additional functionality through inheritance to override its behavior.

What is a sealed class in Java?

It is a sealed class. We have different types of nested classes and remain the state. Sealed class allows us to represent hierarchies. And it prevents inheritance, this class is sealed, so use nested child classes. Sealed class over abstract class:

Can a sealed class contain abstract methods?

This sealed class cannot contain abstract methods. It should be the bottom-most class within the inheritance hierarchy. A sealed class can never be used as a base class. The sealed class is specially used to avoid further inheritance. The keyword sealed can be used with classes, instance methods, and properties.

What is the difference between sealed class and nested class?

We have different types of nested classes and remain the state. Sealed class allows us to represent hierarchies. And it prevents inheritance, this class is sealed, so use nested child classes. Sealed class over abstract class:

What is a sealed class in Kotlin?

Kotlin provides its own approach. It is a sealed class. We have different types of nested classes and remain the state. Sealed class allows us to represent hierarchies. And it prevents inheritance, this class is sealed, so use nested child classes.


Video Answer


1 Answers

The warning “Parent is a raw type” is entirely unrelated to sealed classes, as using extends Parent when Parent<T> is a generic class will cause such a warning since Generics exist.

You most probably want to use

public non-sealed class ChildA<T extends FileTypeA> extends Parent<T> {}

public non-sealed class ChildB<T extends FileTypeB> extends Parent<T> {}

The other issue seems to be an Eclipse bug, as I can only reproduce the warning there. When I change the declaration to permits ChildA<?>, ChildB<?>, the warning disappears, but you should not do this.

The Java Language Specification defines the permits clause as

ClassPermits:
    permits TypeName {, TypeName}

whereas TypeName is linked to

TypeName:
    TypeIdentifier
    PackageOrTypeName . TypeIdentifier

PackageOrTypeName:
    Identifier
    PackageOrTypeName . Identifier

This clearly leads to a sequence of dot separated identifiers without any type parameters. Consistently, javac rejects a construct like permits ChildA<?>, ChildB<?>.

In other words, Eclipse should not generate a warning here and even more importantly, not accept parameterized types in a permit clause. Your best option is to wait for a fix of Eclipse’s Java 17 support. You could add a @SuppressWarnings("rawtypes") to the entire Parent class to make the warning go away, but since that would affect the entire class, I do not recommend it.

like image 90
Holger Avatar answered Oct 23 '22 15:10

Holger