For example I have a class MyClass and two other classes that process the object of MyClass.
Class A - Creates MyClass;
Class B - uses MyClass;
What is the proper way to store and share the MyClass object among A and B. Need to create MyClass with new operator and store the pointer in unique_ptr. Or implement move c-tor, and create MyClass as stack variable?
Variant 1:
class A
{
public :
unique_ptr<MyClass> mObj;
};
class B
{
B( unique_ptr<MyClass> inObj ) : mObj( inObj ) {};
public :
unique_ptr<MyClass> mObj;
}
Variant 2:
class A
{
public :
MyClass mObj;
};
class B
{
B( MyClass&& inObj ) : mObj( inObj ) {};
public :
MyClass mObj;
};
Using:
A a;
B( a.mObj );
In both of your examples class A can not use myObj after B has taken over! This may not be what you what. However if it is intended, than I would recommend using unique_ptr. Here it is clear, if and when A has lost access to myObj. You can test for is by checking if myObj is a null pointer.
Neither of proposed solutions are going to work, because both as member variable, and with unique_ptr, you have two independent objects.
If you need to access the same object, either use std::shared_ptr, or use references.
With shared_ptr :
class A
{
public :
A() : mpObj( new MyClass ) {}
shared_ptr<MyClass> mpObj;
};
class B
{
public :
B( shared_ptr<MyClass> inObj ) : mpObj( inObj ) ;
shared_ptr<MyClass> mpObj;
};
Another option is to use references :
class A
{
public :
A() : mpObj() {}
MyClass mpObj;
};
class B
{
public :
B( MyClass& inObj ) : mpObj( inObj ) ;
MyClass& mpObj;
};
What is important is to say who creates and initialize the MyClass object.
Also, read about Dependency injection.
Related
I've been working on an item system for my game in Unity. I am still pretty new to coding, but I am giving it my best effort.
My Item system Works by accessing interfaces with the data I need. While trying to assign my sprite from the interface to a private variable, I get the error "'Sprite' does not contain a constructor that takes 0 arguments." I have looked all over for solutions, and haven't found any fixes that have worked for me so far.
The Class I created to access the interface looks like this:
public class ISType : IISType {
[SerializeField] string _name;
[SerializeField] Sprite _icon;
ISType()
{
_name = "Type";
_icon = new Sprite(); }
public string Name
{
get
{ return _name; }
set
{ _name = value }
}
public Sprite Icon {
get
{ return _icon; }
set
{ _icon = value; }
}
}
If anyone can tell what is going on I would really appreciate the help! :)
It looks like Sprite does not contain a public constructor accepting zero arguments.
A class with no constructors defined will have a parameterless constructor.
public class MyClass { }
MyClass x= new MyClass(); // this is valid
However if it has any other constructors defined, this parameterless 'default' constructor is no longer 'a given'.
Difference between default constructor and paramterless constructor?
Answer by Nicole Calinoiu
The "default" constructor is added by the C# compiler if your class does not contain an explicit instance constructor. It is a public, parameterless constructor.
https://stackoverflow.com/a/10498709/5569485
public class MyClass {
public MyClass(string foo)
{
}
}
MyClass x= new MyClass(); // this is invalid
The class would have to manually define a parameterless constructor.
public class MyClass {
// parameterless constructor
public MyClass()
{
}
public MyClass(string foo)
{
}
}
MyClass x= new MyClass(); // this is valid again!
Sometimes no constructors are provided publicly, and a class instead provides static methods to instantiate the object.
public class MyClass
{
private MyClass()
{
}
public static MyClass Create()
{
return new MyClass();
}
}
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/private-constructors
A private constructor is a special instance constructor. It is generally used in classes that contain static members only. If a class has one or more private constructors and no public constructors, other classes (except nested classes) cannot create instances of this class.
Without knowing more about the Sprite class, my guess is that there is a static method for creating instances of the Sprite
something like
Sprite sprite = Sprite.Create(...);
The answer is in the error. There is no constructor that takes 0 parameters for Sprite. Without seeing the code I'm guessing you made a custom constructor with parameters and didn't add a paramaterless one.
A default parameterless constructor would look like:
Sprite()
{}
Be sure to do a lot more reading and tutorials. This is fairly basic class information.
This is giving an error:
class Apple(weightInGrams: Float){
fun grow() {
weightInGrams+= 2.0f
}
}
First of all, the equivalent of void (in Java) is Unit (in Kotlin), and the type a function returns goes at the end, so you should use fun grow(): Unit { ... } instead of fun void grow() { ... }. Moreover, you can omit Unit and just write fun grow() { ... } because the compiler knows that your function doesn't return any meaningful value.
Now, I'll try to explain the basics to answer your question and give you some clarity. In Java, the parameters of a constructor are visible only inside that constructor. In Kotlin, the parameters are only visible in initializer blocks and in property initializers, unless you transform them into properties. Let's explain all this with examples.
In Java, we see constructors in classes like this many times:
public class Person {
public final String name;
public final Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
}
The parameters are used to initialize the fields of the class Person.
In Kotlin, the equivalent could be:
a) Use the parameters in initializer blocks.
class Person(name: String, age: Int) {
val name: String
val age: Int
init {
this.name = name
this.age = age
}
}
b) Use the parameters in property initializers declared in the class body.
class Person(name: String, age: Int) {
val name = name
val age = age
}
c) Declaring properties and initializing them directly in the primary constructor.
class Person(val name: String, val age: Int)
Therefore, if you write var or val, the parameters of the constructor will be also properties and you will be able to use them in your class like you want to do inside your function grow.
So, your final code should be:
class Apple(var weightInGrams: Float) {
fun grow() {
weightInGrams += 2.0f
}
}
var because you are assigning a value to weightInGrams multiple times.
make your property a class member
class Apple(var weightInGrams: Float){
fun void grow() {
weightInGrams+= 2.0f
}
}
I understand the question was already answered.
If you want to initialize an apple with an initialWeight, you can do it as below. The init block can help initialize the value and the grow function can effectively work on the actual variable without a need to declare the constructor variable as var:
class Apple(initWeight: Float){
var weightInGrams = 0.0f
init {
var weightInGrams = initWeight
}
fun grow() {
weightInGrams+= 2.0f
}
}
fun main(args: Array<String>) {
val a = Apple(10.0f)
a.grow()
println(a.weightInGrams)
};
I have a base class (with which I want to simulate interfaces)
template<typename TType>
class Base
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() = 0;
}
and obviously a derived class
template<typename TType>
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() = 0;
}
but for some specific type I have the intention to specialize the 'GetTheObject'
template<>
SomeTemplatedClass<int> Derived<int>::GetTheObject()
{
return 5;
}
Visual Studio 2015 complains it cannot instantiate abstract class, when I try to use
Derived<int>
Providing even a throwing behavior to a template version
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() override
{
throw <something>;
}
}
Let everything compile.
So my question is: Why do i need to provide a generic behavior, when I have a specific one and the only one that is needed?
You don't need to implement the generic GetTheObject, but you need to declare it as non-pure. Otherwise your class is abstract.
template<typename TType>
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject();
}
You can specialise the function now.
You won't be able to instantiate any non-specialised derived objects (you will get linker errors).
You cannot make an abstract class into concrete by simply providing an implementation of its pure virtual member outside of the class.
class A { virtual void f() = 0; }; // A is abstract
void A::f() {} // A is still abstract
Templates are no different.
template <int> class A { virtual void f() = 0; }; // A is abstract
template <int k> void A<k>::f() {} // A is still abstract
A function specialisation changes nothing.
template <int> class A { virtual void f() = 0; }; // A is abstract
template <int k> void A<k>::f() {} // A is still abstract
template <> void A<42>::f() {} // srsly are you kidding?
If you want the generic case to be abstract and the specialised case concrete, you need to specialise the entire class, not just the pure function implementation.
In Java Method References
ContainingClass::staticMethodName - means that a class can refer the static method (Reference to a Static Method )
containingObject::instanceMethodName - means that a class object is created first and then that object is used to refer the instanceMethod .
My doubt is
ContainingType::methodName - what does the ContainingType mean ?
Is ContainingType a predefined class in java like String or something else ?
Java Language Specification, §4.3. Reference Types and Values:
There are four kinds of reference types: class types (§8.1), interface types (§9.1), type variables (§4.4), and array types (§10.1).
Array type don't have static methods, so that doesn't apply to static method reference, but you can do the other 3:
class MyClass {
static void doIt() {/*doing it*/}
}
interface MyInterface {
static void doIt() {/*doing it*/}
}
class Test<T extends MyClass> {
void test() {
Runnable m1 = MyClass::doIt; // class type
Runnable m2 = MyInterface::doIt; // interface type
Runnable m3 = T::doIt; // type variable
}
}
Now that link is provided in a comment, it says:
Reference to a static method
ContainingClass::staticMethodName
Reference to an instance method of a particular object
containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type
ContainingType::methodName
Reference to a constructor
ClassName::new
Here, again, ContainingType refers to any of the 3 reference types mentioned above: Class, Interface, and Type Variable.
You can then make a method reference for any instance method of such a type.
class MyClass {
void doIt() {/*doing it*/}
}
interface MyInterface {
void doIt();
}
class Test<T extends MyClass> {
void test() {
Consumer<MyClass> m1 = MyClass::doIt;
Consumer<MyInterface> m2 = MyInterface::doIt;
Consumer<T> m3 = T::doIt;
}
}
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
In the document you gave,there is a example of the ContainingType:
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
and explains:
The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).
I think,the element of the stringArray dosen't have a name (eg: String s1 = "Barbara"),so you can't refer it by containingObject::instanceMethodName(eg:s1::compareToIgnoreCase). That's why it uses ContainingType.
I think your ContainingType::methodName is a general/common form of the 2 forms above...
Think about the below code. You can replace the <methodReference> width
InterfaceA::method (for ContainingType::methodName)
ClassA::method (for also ContainingType::methodName)
ClassB::instanceMethod (for ContainingObject::instanceMethodName) or
ClassB::staticMethod (for ContainingClass::staticMethodName)
to demonstrate the mentioned cases:
public class App {
interface InterfaceA {
String method();
}
static class ClassA implements InterfaceA {
public String method() {
return "ContainingType::methodName";
}
}
static class ClassB extends ClassA {
public String instanceMethod() {
return "ContainingObject::instanceMethodName";
}
public static String staticMethod(ClassB classB) {
return "ContainingClass::staticMethodName";
}
}
public static void main(String[] args) {
System.out.println(((Function<ClassB, String>) <methodReference>).apply(new ClassB()));
}
}
I have an issue, i need to list all the interfaces that are anyhow related to the class? –
For ex:
class Test : interface1
{
public int var1;
classA obj1;
classB obj2;
classC obj3;
}
class classA: interface2
{
testclass obj;
}
class classB: interface3
{
}
class classC: interface4
{
}
class testclass: testinterface
{
myinterface objInterface;
}
interface myinterface{}
My question is how do I list all the interfaces of class Test (it should return all the interfaces anyhow related to the class ex:. interface1, interface2 etc.,).
Anyone help me please?
Thanks in advance
With your current code (almost nothing public, fields instead of properties, etc...), you could do something like that :
var type = typeof(Test);
var interfaces = type.GetInterfaces().ToList();
interfaces.AddRange(type.GetFields(BindingFlags.NonPublic|BindingFlags.Instance)
.SelectMany(x => x.FieldType.GetInterfaces()));
this won't retrieve interfaces of public int var1, as it's... public.
This probably won't fit your exact needs, but without real code and real expected result, it's quite hard to give a better answer.
EDIT
With recursion and your sample, in a console app :
private static void Main()
{
var type = typeof(Test);
var interfaces = type.GetInterfaces().ToList();
GetRecursiveInterfaces(type, ref interfaces);
}
private static IList<Type> GetFieldsType(Type type)
{
return type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Select(m => m.FieldType).ToList();
}
private static void GetRecursiveInterfaces(Type type, ref List<Type> interfaces)
{
foreach (var innerType in GetFieldsType(type))
{
interfaces.AddRange(innerType.IsInterface
? new[] { innerType }
: innerType.GetInterfaces());
GetRecursiveInterfaces(innerType, ref interfaces);
}
}