There’s a number of issues to unpack here.
First:
This is not correct. You do not indicate the context where the code you’ve excerpted is written, but if it is within the body of class Alpha<T>
, then Alpha
is a shorthand for Alpha<T>
, not Alpha<SomeOtherClass>
.
To put it concretely, if a user instantiates a value of type Alpha<SubclassOfSomeOtherClass>
, then the implicit T
is SubclassOfSomeOtherClass
, not SomeOtherClass
.
Second:
Not only is that not the behavior when you write instance is Foo
, but in the general case where Foo<T, U, V>
has arbitrary generic parameters, there exists no operation whatsoever which does what you describe.
That is because, if instance is XXX
is true, then instance as! XXX
succeeds and gives you a result with the static type XXX
. However, there is no such thing as a “type Foo
without generic parameters” that you can use on the right-hand side of an as!
cast.
You would need another additional abstraction, such as a FooProtocol
(which can now make use of primary associated types for parameterization) to accomplish something like what you describe.
Third:
With respect to the expectation, even if all of the above were not the case, it would be undesirable for refactoring a non-generic class to a generic class to behave how you describe.
Given Bar<T>
, Bar<Int>
and Bar<String>
are distinct types. With a non-generic Bar
, the query is Bar
asks whether a given instance has the dynamic type of a specific concrete type Bar
—a user may then want to compare two instances with ==
if the dynamic types match, for instance. It would be very alarming for the same statement, untouched, within the implementation of a refactored generic Bar
to somehow lead to an illogical attempt to equate an instance of type Bar<Int>
to an instance of type Bar<String>
.
Fourth:
Generics allow you to reason about polymorphism using the static type system, while is
and as!
allow you to conditionalize behavior based on the dynamic type of instances.
There are sometimes—sometimes—good reasons to mix the two. However, as a general rule of thumb, if you are both the API author and user and you’ve used generics when you authored the API, but now you find that as the user you immediately want to abstract away the generic parameters because you need the dynamism, there is probably a deeper design problem.
Without knowing the specifics of why you refactored to make your class generic, based on the use case you’re describing cursorily here, I’d suggest that your original design was the more appropriate one.