This code fails to compile:
public class Component<T1>
{
public virtual void Foo(T1 t1)
{
return;
}
}
public class Panel<T1>
where T1: Component<Panel<T1>>
{
public void Bar() {
Console.WriteLine("Win");
}
}
public class MyFormPanel : Panel<MyFormPanel.Form>
{
public class Form : Component<MyFormPanel>
{
public override void Foo(MyFormPanel t1)
{
t1.Bar();
}
}
}
The error given is that the the MyFromPanel.Form cannot be used as a type parameter T1 since there is no implicit reference conversion from MyFormPanel.Form to Component<Panel<MyFormPanel.Form>>
This seems confusing to me because a Form inherits from Component, where MyFormPanel is a Panel. Why is this error happening then?
Related
Here is an example of what I am looking to do.
public class ParentA {}
public class ChildA : ParentA
{
public string x;
}
public class A
{
public virtual void DoSomething(Parent a)
{
// perform something
}
}
public class B : A
{
public Override void DoSomething(Child a)
{
// perform something slightly different using both strings
a.x = "something";
}
}
but turn out I got an error with "No Suitable Method found to Override".
So I want to override DoSomething from class A and pass a different set of child class parameter. Is this possible?
When you override something, the signature of the method has to be the same.
So in your case, you can do something like this
public class Parent { }
public class Child : Parent
{
public string x;
}
public class A
{
public virtual void DoSomething(Parent a)
{
// perform something
}
}
public class B : A
{
public override void DoSomething(Parent a)
{
if (a is Child child)
{
// perform something slightly different using both strings
child.x = "something";
}
}
}
I'm not 100% sure exactly what you're trying to accomplish, however generics may help you:
public class Parent { }
public class Child : Parent
{
public string x;
}
public class A<T> : Parent where T : Parent
{
public virtual void DoSomething(T a)
{
}
}
public class B : A<Child> // Child could also be Parent here
{
public override void DoSomething(Child a)
{
a.x = "test";
}
}
I'm trying to do something like this but I'm getting an error along the lines of:
Cannot convert from AbstractExampleClass to SpecificExampleClassA.
So I'm probably going in the wrong direction with this code, can anyone tell me what's wrong and how to fix it.
public abstract class AbstractExampleClass
{
// Code goes here
}
public class SpecificExampleClassA : AbstractExampleClass
{
}
public class SpecificExampleClass : AbstractExampleClass
{
}
public class handler
{
public void Handle(AbstractExampleClass aec)
{
HandleSpecific(aec);
}
public void HandleSpecific(SpecificExampleClassA a)
{
// DoSomething
}
public void HandleSpecific(SpecificExampleClassB b)
{
// DoSomething Else
}
}
Overloading is resolved at compile time, so you can't expect it to decide which overload to call depending on the runtime type of aec. The overload to call must be decided at compile time.
What you really need here is the "subtyping" kind of polymorphism (aka just "polymorphism" in C# terminology), not ad hoc polymorphism (aka "overloading").
Move the handler methods in the subclasses instead:
public abstract class AbstractExampleClass
{
public abstract void Specific();
}
public class SpecificExampleClassA : AbstractExampleClass
{
public override void Specific()
{
// DoSomething
}
}
public class SpecificExampleClass : AbstractExampleClass
{
public override void Specific()
{
// DoSomething Else
}
}
public class handler
{
public void Handle(AbstractExampleClass aec)
{
aec.Specific();
}
}
That can be handled by the Visitor Pattern
public abstract class AbstractExampleClass
{
public abstract void Accept( Handler handler );
}
public class SpecificExampleClassA : AbstractExampleClass
{
public override Accept( Handler handler )
{
handler.HandleSpecific( this );
}
}
public class SpecificExampleClass : AbstractExampleClass
{
public override Accept( Handler handler )
{
handler.HandleSpecific( this );
}
}
public class Handler // the Visitor
{
public void Handle(AbstractExampleClass aec)
{
aec.Accept( this );
}
public void HandleSpecific(SpecificExampleClassA a) // visit method
{
// DoSomething
}
public void HandleSpecific(SpecificExampleClassB b) // visit method
{
// DoSomething Else
}
}
If you really have to do it that way, you can do:
public void Handle(AbstractExampleClass aec)
{
switch (aec)
{
case SpecificExampleClassA a:
HandleSpecific(a);
break;
case SpecificExampleClassB b:
HandleSpecific(b);
break;
default:
throw new Exception($"What do I do with a '{aec?.GetType()}'?");
}
}
But I recommend an approach like the one in Sweeper's answer if you are allowed to do that.
consider the following game code:
public class Player : MonoBehaviour {
public void UseItem(Item item) {
item.Use(this);
}
public void GetDrunk() {}
}
public class Item {
public WhatInterface[] itemUsages;
public void Use(Player player) {
foreach(var usage in itemUsages) {
usage.Execute(new ItemUsageArgs {itemUser = player, itemUsed = this})
}
}
}
public class GameManager : MonoBehaviour {
public Player mainCharacter;
public Item beer = new Item {itemUsages = new [] {
new TestConsole(),
new DamageFromItem (),
new DrunkFromITem ()
}}
private void Start() {
mainCharacter.Use(beer);
}
}
public class TestConsole : WhatInterface {
public void Execute(BaseArgs args) {
Debug.Log("function call executed");
}
}
public class DamageFromItem : WhatInterface {
public void Execute(ItemUsageArgs args) {
Debug.Log(args.itemUser + " take damage from " + args.itemUsed);
}
}
public class DrunkFromITem : WhatInterface {
public void Execute(ItemUsageArgs args) {
args.itemUser.GetDrunk();
}
}
public class BaseArgs {}
public class ItemUsageArgs : BaseArgs {
public Player itemUser;
public Item itemUsed;
}
so how to create interface type code that is suited for itemUsages?
Or do I wrongly create the design for this context?
Basically I'm trying strategy pattern so that item usages could be vary for every kind of item.
Things I tried, creating IItemUsage interface:
public interface IItemUsage {
void Execute(ItemUsageArgs args);
// but then anything that needs to implement this interface must use this method, even though it only needs BaseArgs.
// TestConsole class must conform to Execute(ItemUsageArgs) signature..
}
public class TestConsole : IItemUsage {
public void Execute(BaseArgs args) {
Debug.Log("function call executed");
}
// this won't compile
}
Assuming this is all of your code, you can make IItemUsage generic, and contravairant on the generic parameter.
public interface IItemUsage<in T> where T: BaseArgs {
void Execute(T args);
}
Have TestConsole implement IItemUsage<BaseArgs> and the other two classes implement IItemUsage<ItemUsageArgs>.
Now you can put instances of all three classes into an IItemUsage<ItemUsageArgs>[]:
IItemUsage<ItemUsageArgs>[] arr = new IItemUsage<ItemUsageArgs>[] {
new TestConsole(), new DamageFromItem(), new DrunkFromITem()
};
If you want to implement interface with some method, which has input arguments, that can be different types, you must define base argument class or use interface parameter instead.
For example:
public interface IItemUsage
{
void Execute(IItemUsageArgs args);
}
public interface IItemUsageArgs
{
//place public part of all ItemUsageArgs
}
public class ItemUsageArgs1 : IItemUsageArgs
{
}
public class ItemUsageArgs2 : IItemUsageArgs
{
}
public class ItemUsage1 :IItemUsage
{
public void Execute(ItemUsageArgs1 args)
{
//do you need
}
void IItemUsage.Execute(IItemUsageArgs args)
{
Execute(args as ItemUsageArgs1);
}
}
public class ItemUsage2 : IItemUsage
{
public void Execute(ItemUsageArgs2 args)
{
//do you need
}
void IItemUsage.Execute(IItemUsageArgs args)
{
Execute(args as ItemUsageArgs2);
}
}
I am trying to implement two level inheritance. Currently, there is an abstract class and an inherited class :
public abstract class A
{
public abstract void func();
}
public class B : A
{
public override void func()
{
.......
}
}
I would like to create two specialized instances of class B but I want those functions to be exposed by class A. I am going for,
public abstract class A
{
public abstract void func();
}
public class B : A
{
public virtual void func();
}
public class C : B
{
public override void func()
{
........
}
}
public class D : B
{
public override void func()
{
........
}
}
This implementation is wrong but that is my intent. How will I implement this ?
You can use interface instead of abstract class A like this:
public interface A
{
void func();
}
public abstract class B: A
{
public abstract void func();
}
public class C : B
{
public override void func()
{
throw new NotImplementedException();
}
}
public class D : B
{
public override void func()
{
throw new NotImplementedException();
}
}
May be it helps you.
You cannot have virtual method without implementation, so instead you should make class B abstract, which should make compiler happy:
public abstract class B : A
{
}
Alternative approach is to add empty method body for function func:
public class B : A
{
public virtual void func()
{
// function has empty method body
// it does not do anything, but you can override functionality in derived classes
}
}
I want to create a class that can only be inherited, for that i know it should be made abstract. But now the problem is that i want to use functions of that class without making them static. How can i do that.
public abstract Class A
{
A()
{}
public void display()
{}
}
public Class B:A
{
base.A() // this is accessible
this.display() // this is not accessible if i dont make this function static above
}
Your example will not compile, you could consider something like this:
using System;
public abstract class A
{
protected A()
{
Console.WriteLine("Constructor A() called");
}
public void Display()
{
Console.WriteLine("A.Display() called");
}
}
public class B:A
{
public void UseDisplay()
{
Display();
}
}
public class Program
{
static void Main()
{
B b = new B();
b.UseDisplay();
Console.ReadLine();
}
}
Output:
Constructor A() called
A.Display() called
Note: Creating a new B() implicitly calls A(); I had to make the constructor of A protected to prevent this error:
"'A.A()' is inaccessible due to its protection level"
That's not true. You don't have to make Display() static; you can call it freely from the subclass. On the other hand, you can't call the constructor like that.
Maybe it's just an error in the example, but the real issue with the code you have is that you can't put method calls in the middle of your class definition.
Try this:
public abstract class A
{
public void Display(){}
}
public class B:A
{
public void SomethingThatCallsDisplay()
{
Display();
}
}
Here's how you can do this..
public abstract class A
{
public virtual void display() { }
}
public class B : A
{
public override void display()
{
base.display();
}
public void someothermethod()
{
this.display();
}
}