Why doesn't this method invocation invoke the derived class? - c#

I have an interface IDeepCloneable, that I'm using to implement generic deep copying. I have a base class and a derived class as well, each implementing IDeepCloneable. I'm running into issues with derived classes.
Here is the code:
public class Program
{
public static void Main()
{
var a = new BaseClass();
var ac = a.DeepClone();
var b = (BaseClass)(new DerivedClass());
var bc = b.DeepClone();
}
}
public interface IDeepCloneable<T>
{
T DeepClone();
}
public class BaseClass : IDeepCloneable<BaseClass>
{
public string Value { get; set; }
public BaseClass(){}
public BaseClass(BaseClass copy)
{
Value = copy.Value;
}
public BaseClass DeepClone()
{
Console.WriteLine("BLAH1");
return new BaseClass(this);
}
}
public class DerivedClass : BaseClass, IDeepCloneable<DerivedClass>
{
public string SomeOtherValue { get; set; }
public DerivedClass(){}
public DerivedClass(DerivedClass copy)
: base(copy)
{
SomeOtherValue = copy.SomeOtherValue;
}
public new DerivedClass DeepClone()
{
Console.WriteLine("BLAH2");
return new DerivedClass(this);
}
}
This outputs:
BLAH1
BLAH1
I understand why it outputs BLAH1 twice, I'm just not sure how to fix it..

Your derived class needs to override the DeepClone() method, and your DeepClone method in the base class needs to be virtual.
Right now, your DeepClone method in the derived class is unrelated (other than having the same name) to the base class. See Interface Implementation Inheritance in the C# standard.
That said, it looks like you're trying to do deep copies. Have you considered using a BinaryFormatter to serialize and de-serialize your data?

since that base class or yours implements the interface already, so you can either make the base class's DeepClone method as virtual and override it, or you can do
public abstract class BaseClass : IDeepCloneable<T>
...
public abstract T DeepClone(){}
and in your DerivedClass do
public class DerivedClass : BaseClass<DerivedClass>

Related

Why is covariance not working as expected? [duplicate]

This question already has answers here:
C#: Overriding return types
(15 answers)
Closed 2 years ago.
Why is this not working? The compiler should be smart enough to know that InterfaceB requires InterfaceA and therefore must be compatible.
public interface InterfaceA
{ }
public interface InterfaceB : InterfaceA
{ }
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; set; } // Error, needs to be InterfaceA
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; set; }
}
Why is that?
The compiler should be smart enough to know that InterfaceB requires InterfaceA and therefore must be compatible.
But it's not compatible - you could do this:
DerivedClass derived = new DerivedClass();
InterfaceB ib = new InterfaceBImpl();
derived.ItemService = ib; // good so far
InterfaceA ia = new InterfaceAImpl(); // still good
BaseClass bc = derived; // still a legal downcast
bc.ItemService = ia; // seemingly good - BaseClass can store an InterfaceA
ib = derived.ServiceImpl;
Here is where it blows up. You have stored an object that does not implement InterfaceB in a property that should require an InterfaceB.
One common way to do what you want is still generics:
public abstract class DerivedClass : BaseClass<InterfaceB>
{
//protected override InterfaceB ItemService { get; set; } // Error, needs to be InterfaceA
// no override needed - ItemService will now be of type InterfaceB
}
public abstract class BaseClass<T> where T : InterfaceA
{
protected T ItemService { get; set; }
}
I'll admit that I haven't studied up on C# 9 much yet, but from what I see the covariant returns only apply to methods and get-only properties. If that were the case here, your solution would be fine. It's the setter that allows you to break the type system in this case.
It also seems that read-only properties are supported, so you may be able to do this:
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; }
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; }
}
the base class says any InterfaceA can be assigined to ItemService, so a derived class can't change that to say "Only InterfaceB can be assigned to it". But if you ditch the assignment, so it is :-
public interface InterfaceB : InterfaceA
{
}
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; } // no set
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; }
}
it will work, as there is no assignment....but I'm not sure your actual goal

How to downcast this to the base class?

I have this class hierarchy:
public abstract class AClass : SomeFrameworkClass {
[WorkOnThisProperty(With.Some.Context)]
private MyObject MyProperty { get; set; }
public override void OnSomethingHappened() {
ExternalFramework.WorkOn(this);
}
}
public class BClass : AClass {
// ... Snip ...
}
ExternalFramework is operating on this: an instance of BClass but i need it to operate on this as an instance of AClass because ExternalFramework only works on the type of the object passed in and does not go up the inheritance hierarchy. How can i downcast this into AClass so ExternalFramework can actually detect MyProperty?
I've tried casting this to object and then to AClass, and casting it directly to AClass but as the cast is unnecessary it doesn't seem to run. What can i do about this?
EDIT: ExternalFramework is Cheeseknife. I am trying to inject a couple views into a base fragment class that has all the reusable logic while child fragment classes implement some specific behaviour tuning.
The problem is that all private members of a class can only be accessed inside of the same class.
With this code:
class A { private string Property { get; set; } }
class B : A { public string Proxy => Property; }
We'll get compilation error because class B cannot access private property from class A, but if change keyword to protected :
class A { protected string Property { get; set; } }
It should work.

Difference between abstract class constructor and normal class constructor?

abstract class Animal
{
public string DefaultMessage { get; set; }
public Animal()
{
Console.WriteLine("Animal Cstor called");
DefaultMessage = "Default Speak";
}
public virtual void Speak()
{
Console.WriteLine(DefaultMessage);
}
}
class Dog : Animal
{
public Dog()
: base()//base() redundant. There's an implicit call to base here.
{
Console.WriteLine("Dog cstror called");
}
public override void Speak()
{
Console.WriteLine("Custom Speak");//append new behavior
base.Speak();//Re-use base behavior too
}
}
or else
class Animal
{
public string DefaultMessage { get; set; }
public Animal()
{
Console.WriteLine("Animal Cstor called");
DefaultMessage = "Default Speak";
}
public virtual void Speak()
{
Console.WriteLine(DefaultMessage);
}
}
class Dog : Animal
{
public Dog()
: base()//base() redundant. There's an implicit call to base here.
{
Console.WriteLine("Dog cstror called");
}
public override void Speak()
{
Console.WriteLine("Custom Speak");//append new behavior
base.Speak();//Re-use base behavior too
}
}
what is the Difference between abstract class constructor and normal class constructor?
No difference rather than an abstract class constructor can't be called publicly because otherwise it would defeat the purpose of abstract classes (i.e. they must be inherited and cannot be instantiated directly, thus an abstract class public constructor can be only called by a derived class constructor!).
Whilst you cannot instantiate an abstract class it may have a constructor that is called from a derived one. Thus an abstract one should never be public but protected. So the only difference from an API-point of view is that the first cannot be called directly from any arbitrary class while a normal constrcutor can be called allways from everywhere (depending on access-modifier of course).
To be more precise: an Animal-class should probably NEVER be not-abstract. That would mean that there are animals existing that cannot be categorized any further to Cats, Dogs or whatever, but only animals.

Can you override one of the abstract methods in a base class with another base class?

I have a base class that has some abstract methods on it and there are 21 classes that are inheriting from this base class. Now for one of those abstract methods I want to implement it with a common implementation for 6 of the 21 classes so I thought about creating another base class that would do this.
I am open to suggestions but my main purpose of creating another base class between the current base class and the 21 classes is to keep from repeating the same code in 6 of the 21 classes if I didn't have to.
Here is a sample of code to illustrate the situation:
public abstract class FooBase
{
public abstract string Bar();
public abstract string SomeMethod();
public virtual string OtherMethod()
{
return this.SomeMethod();
}
}
public abstract class AnotherBase : FooBase
{
public abstract string Bar();
public abstract string SomeMethod();
public override OtherMethod()
{
//this is the common method used by 6 of the classes
return "special string for the 6 classes";
}
}
public class Foo1 : FooBase
{
public override string Bar()
{
//do something specific for the Foo1 class here
return "Foo1 special string";
}
public override string SomeMethod()
{
//do something specific for the Foo1 class here
return "Foo1 special string";
}
}
public class Another2 : AnotherBase
{
public override string Bar()
{
//do something specific for the Another2 class here
return "Another special string";
}
public override string SomeMethod()
{
//do something specific for the Another2 class here
return "Another2 special string";
}
}
Yes, you can derive an abstract class from another abstract class
public abstract class FooBase
{
//Base class content
}
public abstract class AnotherBase : FooBase
{
//it is "optional" to make the definition of the abstract methods of the Parent class in here
}
When we say it is optional to define the abstract methods of the parent class inside of the child class, it is mandatory that the child class should be abstract.
public abstract class FooBase
{
public abstract string Bar();
public abstract string SomeMethod();
public abstract string OtherMethod();
}
public abstract class AnotherBase : FooBase
{
public override string OtherMethod()
{
//common method that you wanted to use for 6 of your classes
return "special string for the 6 classes";
}
}
//child class that inherits FooBase where none of the method is defined
public class Foo1 : FooBase
{
public override string Bar()
{
//definition
}
public override string SomeMethod()
{
//definition
}
public override string OtherMethod()
{
//definition
}
}
//child class that inherits AnotheBase that defines OtherMethod
public class Another2 : AnotherBase
{
public override string Bar()
{
//definition
}
public override string SomeMethod()
{
//definition
}
}
So I'm guessing that there will be 5 more classes like Another2 which inherits from AnotherBase that will have a common definition for OtherMethod
Yes, that is entirely possible and frequently done. There is no rule that says that you can have only one base class at the bottommost level of your class hierarchy; subclasses of that class can just as well be abstract and thereby become (somewhat more specialized) base classes for one group of classes indirectly derived from your general base class.
You should specify what exactly those classes do, but.. given the information you provided:
This is the exact problem that the Strategy pattern aims to solve, as shown in the example given in the Head First Design Patterns book.
You have an abstract Duck class, from which other ducks (e.g., RedheadDuck, MallardDuck) derive. The Duck class has a Quack method, that simply displays the string "quack" on the screen.
Now you are told to add a RubberDuck. This guy doesn't quack! So what do you do? Make Quack abstract and let the subclasses decide how to implement this? No, that'll lead to duplicated code.
Instead, you define an IQuackBehaviour interface with a Quack method. From there, you derive two classes, QuackBehaviour and SqueakBehaviour.
public class SqueakBehaviour: IQuackBehaviour
{
public void Quack(){
Console.WriteLine("squeak");
}
}
public class QuackBehaviour: IQuackBehaviour
{
public void Quack(){
Console.WriteLine("quack");
}
}
Now, you compose your ducks with this behaviour as appropriate:
public class MallardDuck : Duck
{
private IQuackBehaviour quackBehaviour = new QuackBehaviour();
public override void Quack()
{
quackBehaviour.Quack();
}
}
public class RubberDuck : Duck
{
private IQuackBehaviour quackBehaviour = new SqueakBehaviour();
public override void Quack()
{
quackBehaviour.Quack();
}
}
You can even inject an instance of IQuackBehaviour through a property if you want the ducks to change their behaviour at runtime.

Abstract type in constructor instead of Concrete type

I have an object that suppose to be data which is returned to client side after
they calls web method.
// NewData1.cs
public NewData1(Concrete1 con)
{
ID = con.ID;
var results= con.listOfResults();
var something= con.GetSomething();
Something = new List<Somethings>();
con.DoSomething();
}
// NewData2.cs
public NewData2(Concrete2 con)
{
ID = con.ID;
var results= con.listOfResults();
var something= con.GetSomething();
Something = new List<Somethings>();
con.DoSomething();
}
// NewData3.cs
public NewData3(Concrete3 con)
{
ID = con.ID;
var results= con.listOfResults();
var something= con.GetSomething();
Something = new List<Somethings>();
con.DoSomething();
}
As you can see those classes do the same thing (it not my code..i want to change it).
The only different thing is the Concrete types (1,2,3) that do different logic when calling their methods.
Do you know a way to reduce those classes to one class but still make each of them to their special logic and not the same?
If your Concrete1, Concrete2 and Concrete3 classes share same methods, you can extract this into an interface and make them implement it:
// an interface is simply a contract
interface ICanGetSomething
{
int ID { get; }
List<Result> ListOfResults();
Something GetSomething();
}
// your concrete classes should all implement the same interface
class Concrete1 : ICanGetSomething { ... }
class Concrete2 : ICanGetSomething { ... }
class Concrete3 : ICanGetSomething { ... }
This way you only need a single method to handle all of them:
public void NewData(ICanGetSomething con)
{
ID = con.ID;
var results = con.ListOfResults();
var something = con.GetSomething();
...
}
If they also share the same functionality, you can also use a common abstract class to reuse all common code:
abstract class Base : ICanGetSomething { ... }
// your concrete classes should all inherit from the same base class
class Concrete1 : Base { ... }
class Concrete2 : Base { ... }
class Concrete3 : Base { ... }
Either way, I recommend using interfaces for defining contracts. Since C# does not support multiple inheritance, you don't want to force all concrete implementations to derive from a single base class (unless it's necessary). This still means that you will use inheritance where there is shared functionality, but your NewData method should accept the interface for the parameter, not the base class.
You can create an abstract base class from Concrete if all 3 deriving classes have the exact same signatures.
The base class :
public abstract class AbstractBaseClass
{
public long ID { get; set; }
public abstract List<string> ListOfResults();
public abstract string GetSomething();
public abstract void DoSomething();
}
Your concrete derive from it :
public class Concrete1 : AbstractBaseClass
{
public override List<string> ListOfResults()
{
// Logic
}
public override string GetSomething()
{
// Logic
}
public override void DoSomething()
{
// Logic
}
}
Set the argument as the base class :
public void NewData(AbstractBaseClass abs)
{
ID = abs.ID;
var results= abs.listOfResults();
var something= abs.GetSomething();
abs.DoSomething();
}
You can now do, for example :
NewData data = new NewData(new Concrete1());
All calls in NewData constructor will be directed to the Concrete1 child class.
If you can have only one instance of NewData, you can use the Stategy Pattern to change the concrete class when needed.
Create the following base class.
public class Concrete
{
public int ID { get; set; }
public virtual something GetSomething()
{
}
public virtual void DoSomething()
{
}
}
Have your concrete1, concrete2 etc classes extend Concrete. Those classes will be able to override the GetSomething method if they need to.
Then you just need one of these.
public NewData2(Concrete con)
{
ID = con.ID;
var results= con.listOfResults();
var something= con.GetSomething();
Something = new List<Somethings>();
con.DoSomething();
}
You want an abstract base class:
public abstract class BaseClass
{
// Use protected fields to store data that only this class and derived
// classes can access.
protected List<Something> storedSomethings;
//Define an abstract method signature for methods that the concrete classes
// have very different implementations for:
public abstract List<Something>GetSomethings();
//Use a virtual method for methods that are identical or similar on
//the concrete classes:
public virtual void AddSomethings(List<Something> addList)
{
storedSomethings.Add(addList);
}
}
Then your concrete classes are implemented like so:
public class Concrete1 : BaseClass
{
public override List<Something> GetSomethings()
{
//actual logic here
}
//override any other abstract methods
}
public class Concrete2 : BaseClass
{
public override List<Something> GetSomethings()
{
//actual logic here
}
//override any other abstract methods
}
Concrete3 is slightly different, it needs to filter on addsomethings:
public class Concrete3 : BaseClass
{
public override List<Something> GetSomethings()
{
//actual logic here
}
//override any other abstract methods
//For some reason this class doesn't want all somethings, so it overrides
// the base method and filters before calling the base method
public override AddSomethings(List<Something> addList)
{
base.AddSomethings(addList.Where(s => s.Condition == false));
}
}
Now, you should only need one newdata class:
public newdata(BaseClass classInstance)
{
//As long as every method you want to call is defined on BaseClass
// and implemented on the concrete classes, you can just do:
classInstance.GetSomething();
}

Categories