Given the following classes
abstract class SomeAbstractClass { abstract val name: String }
data class DataClass( override val name: String ) : SomeAbstractClass()
class NoDataClass( override val name: String ) : SomeAbstractClass()
For any instance of SomeAbstractClass, can I determine whether it is a data class without relying on type checking?
Some background: this seemed the best way of combining inheritance and data classes to me, as suggested in a different answer. Now, within the initializer block of SomeAbstractClass, I want to throw an exception in case the derived type is not a data class to ensure 'correct' (immutable) implementations of derived types.
Using reflection, the Kotlin class description (KClass) can be obtained using the ::class syntax on the instance you want to investigate (in your case, this::class in the initializer block of the abstract class). This gives you access to isData:
true if this class is a data class.
However, as Oliver points out, data classes can still contain var members, so you likely also want to check whether all member variables (and their member variables recursively) are defined as val to ensure immutability of all deriving classes.
Related
I'm trying to build a better Flowtype definition for Koa library and am kinda stuck.
My idea was to use Generic types to be able to specify customized Context class to Koa, so we can actually typecheck additional fields (populated by middlewares) instead of treating them as any.
so, I have:
declare type Context {…}
declare class Application<T: Context<T>> extends events$EventEmitter {
context: T,
…
}
fine…
but Context has a back-reference to Application, which is a generic dependent on Context. How do I spell this in typelib?
This doesn't look right, as I actually want to use not original Context but the type which was actually used by user
declare type Context {
app: Application<Context>
}
I need to dynamically load classes at runtime in Kotlin. I would like to check that they implement my interface, and if so, all green. Unfortunately, Kotlin's "smart casts" is failing me:
var className = "some.class.Name"
val unsafeClass = Class.forName(className).kotlin
require(unsafeClass.isSubclassOf(MyInterface::class)) {
"Class '$className' is not a MyInterface"
}
val safeClass = unsafeClass as KClass<MyInterface>
^^^^^^^^^^^^^^^^^^^^^^
Unchecked cast: KClass<out Any!> to KClass<MyInterface>
I'm clearly checking that the class implements the given interface. Can I re-phrase this code to avoid the warning?
I tried to test with is KClass<MyInterface> but I get a type erasure error (obviously, because the generic type information disappears at runtime.)
Edit: to clarify, my application needs to read class names "some.class.Name" at startup, during configuration; load those classes; check that they satisfy an interface; and store a Class or KClass reference for later. During runtime, it will use those references to create objects, using cls.createInstance() or such.
My question: is there any way to do so without getting unsafe cast warnings?
I can either get a warning at configuration time, when I cast the KClass<*> to KClass<MyInterface> (even though I required the class to be a subclass) but then I get no warning later on, because .createInstance() on a KClass<MyInterface> class reference returns a type-checked MyInterface instance.
Or, I can store the references as KClass<*>, without warnings at configuration time, but then I'll get the warning in the place where I create the instances, because I'll need to unsafe cast Object instances to MyInterface.
Is there any solution that will satisfy the compiler?
JVM and Kotlin implement generics only at the compiler level. One cannot see generic parameters of a generic class at runtime.
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
At runtime, there is no difference between Class<*> and Class<MyInterface>. These two are the same instance of Class type.
The warning that you have means that you have no information in the generic parameter at runtime, a compiler cannot validate it too, and it only can trust you
I do not see the reason cast the KClass to the KClass<MyInterface>. It is only necessary for an object, not it's class. Also, it probably can be simplified to use Class<*> instead, e.g:
val className = "some.class.Name"
val unsafeClass = Class.forName(className)
require(MyInterface::class.java.isAssignableFrom(unsafeClass)) {
"Class '$className' is not a MyInterface"
}
val safe = unsafeClass.newInstance() as MyInterface
This cast is not only unchecked, it's actually incorrect: because AMyInterfaceImpl::class has type KClass<AMyInterfaceImpl> and KClass is not covariant (for good reason), it does not have the type KClass<MyInterface>. You can see that from this code not compiling:
class AMyInterfaceImpl : MyInterface { ... }
val cls: KClass<MyInterface> = AMyInterfaceImpl::class
So if the cast could be checked, it would fail.
KClass<out MyInterface> would be correct, but I don't think the compiler will understand this and allow smart cast. It's just too rarely useful to teach the compiler.
I started learning ASP.NET MVC and I have got some doubt. How do I check if a class is a Model class in MVC. I have PHP Codeigniter background, where all models inherit CI_Model. It was easy to figure out whether a class is a model class or not by checking instanceof operator but in .NET MVC Model class do not extend any class.
So how do I figure out whether a class is a model class through C# Code? How does MVC framework figure out whether the class is model or not. I have renamed folder from "Models" to "Modelss" but still model binding works with ModelState.IsValid. Any help is greatly appreciated.
Most models in an MVC application are plain old CLR objects (POCOs), that often don't have a base class because it isn't needed. You can change that, if you need to.
In the following examples, lets assume you have a object called param coming in from somewhere.
In C#, you can check if an object is of a certain type in a few ways. You can cast the object to the type, and if you don’t get an exception, the cast was successful. This is not the preferred method any longer, but I wanted you to know if was an option.
try {
var myType = (MyModel)param; // cast happens here
// do something with myType
}
catch{
// cast failed
}
Another way is to use the as operator. This is a much better way to do this because no exception is thrown if the cast fails, you just get null in the variable.
var myType = param as MyModel;
if (myType != null) { // you have what you need.
...
}
Another technique is the is operator (another good way). This works similar to as, but returns a Boolean rather than the object, or null, and you can inline it in an if statement to do the cast, and assign to a variable all in one line of code.
if (param is MyModel myType){
// do something with myType
}
If you do add a base class to your models, you can use that type rather than the class name in the examples above. If you want, you can forego the base class and use a marker interface (an interface with no properties, or functions declared in it), and check for that type.
public interface IModel {}
public class MyModel : IModel {
...
}
if (param is IModel myType){
// do something with myType
}
BTW, changing the folder name in the project didn't make any difference because C# works based on namespaces, and not folder structure, for most application types. As long as the folder and class files are included in the project, and the namespace is referenced, all is good.
Hope you find this information useful!
I interface with two data stores, one of them is RDMS and the other one is LDAP. What I want to do is to have a hierarchy persisted using "superclass-table" in the RDBMS and "complete-table" in LDAP.
Is such a thing possible? That is, can you specify multiple inheritance strategies, separately for each data store in the *.orm files or am I forced to use a single inheritance strategy?
I couldn't find this information in the documentation of DataNucleus, they only thing I'm sure of is that you can put inheritance elements in an .orm file instead of the .jdo but that still doesn't answer my question...
The hierarchy is rather simple and consists of an abstract class and several subclasses like this:
abstract class Foo implements IFoo
{
...
}
class Foo1 extends Foo
{
...
}
class Foo2 extends Foo
{
...
}
...
I tried to configure inheritance in the two *.orm files AND in the .jdo file (having in mind that it's going to get overriden by the former) but I get an exception
Caused by: org.datanucleus.metadata.InvalidMetaDataException: Class "...Foo1..." has been specified with an inheritance strategy of "superclass-table", yet no superclass exists or none exists with its own table!
at org.datanucleus.metadata.AbstractClassMetaData.validateUserInputForInheritanceMetaData(AbstractClassMetaData.java:903)
at org.datanucleus.metadata.ClassMetaData.populate(ClassMetaData.java:214)
at org.datanucleus.metadata.MetaDataManager$1.run(MetaDataManager.java:2393)
at java.security.AccessController.doPrivileged(Native Method)
at org.datanucleus.metadata.MetaDataManager.populateAbstractClassMetaData(MetaDataManager.java:2387)
at org.datanucleus.metadata.MetaDataManager.populateFileMetaData(MetaDataManager.java:2224)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.loadMetaDataForClass(JDOMetaDataManager.java:741)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.getMetaDataForClassInternal(JDOMetaDataManager.java:353)
at org.datanucleus.jdo.metadata.JDOMetaDataManager$MetaDataRegisterClassListener.registerClass(JDOMetaDataManager.java:184)
at javax.jdo.spi.JDOImplHelper.registerClass(JDOImplHelper.java:376)
I then tried to remove the inheritance elements from the .jdo but the enhancer fails with the following message:
Class "...Foo1..." has been specified to use an inheritance strategy of "superclass-table", persisting to the table of class ...Foo..., however this class doesnt have a discriminator specified.
The individual configurations are correct (new-table with discriminator at base-class and superclass-table at subclasses for the first case and complete-table only at base-class for the second).
You can put that information in the orm file, yes, and indeed that does answer your question since you have one ORM file for RDBMS, and one for LDAP. So package-rdbms.orm, and package-ldap.orm, and then simply set persistence property "javax.jdo.option.Mapping" to either "rdbms" or "ldap". Simple
Why is the FxCop rule CA1061 a bad idea?
The docs state that this rule should not be suppressed. If I have class like so:
public class Set<T>
{ List<T> m_backingList;
public bool Contains(T value)
{
return m_backingList.Contains(value);
}
}
then I add a specific implementation like this:
public class CaseInsensitiveSet : Set<String>
{
public bool Contains(object value)
{
string stringValue = value as string;
if (stringValue == null)
return false;
return base.Contains(stringValue);
}
}
the FxCop complains, but I'm not certain why this is such a bad idea. Is there some problem I don't see with this implementation?
The rule states why you're getting the message:
A method in a base type is hidden by
an identically named method in a
derived type when the parameter
signature of the derived method
differs only by types that are more
weakly derived than the corresponding
types in the parameter signature of
the base method.
In your child class, the Contains method takes an object which is more weakly typed than string and therefore hides the parent.
The reason you're getting the warning from FxCop is that this might not be an intentional design choice (since you're not overriding anything or using the new keyword).
Even if it is an intentional design choice, I would argue that it's not necessarily a good one. If you already know that the collection is going to contain strings and nothing else, why would you provide a Contains method that takes anything other than a string? It may appear that you're adding flexibility into the design but, in the end, you're really only going to confuse other developers.
There are also other naming options instead of calling the method Contains which wouldn't hide (intentionally or not) the base Contains method.
Ask yourself: do I want the users to be able to call the base class method on an instance of the derived class.
If the answer is yes: don't hide the base method, as this will make it more cumbersome to use it.
If the answer is no: don't derive from this class, or else they can still access the base method by casting the object to the base class.
http://msdn.microsoft.com/en-us/library/ms182143(VS.80).aspx
A method in a base type is hidden by
an identically named method in a
derived type when the parameter
signature of the derived method
differs only by types that are more
weakly derived than the corresponding
types in the parameter signature of
the base method.
EDIT
Basically you're hiding the base method (public bool Contains in Set), which will never now be run in preference to the derived method. But the derived method is more weakly defined than the base method so there are situations when the base method is the preferable method.