I have 2 classes:
public class Class1
{
private string Name1;
public Class1()
{
//How to get Name2 of the derived class?
}
}
public class Class2 : Class1
{
private string Name2 = "asd";
public Class2(){}
}
How to get Name2 of the derived class in the base constructor?
public class Class1
{
private string Name1;
public Class1()
{
class2 xxx = this as class2
if (class2 != null)
this.Name1 = xxx.Name2;
}
}
"this as class2" - is not null
This example is correct. The only thing is I don't know Derived class is Class2 or class3 or class4 .... I need universal code
You cannot (and more importantly, you should not) do that. When you are in the constructor of the base class, the subclass portion has not been initialized yet, so there is no way to get to the members of the subclass: quite simply, they do not exist yet.
Another problem is that the Name2 attribute may not be present in a subclass at all, even at the level fo the definition: I can derive Class3 from Class1, and give it Name3 attribute instead of Name2.
All this does not touch on such "insignificant" matters as breaking encapsulation: Name2 is a private member, which may be removed in the future implementations of the Class2.
The only way for the subclass to communicate things to superclass in a constructor is passing parameters. This would work:
public class Class1 {
private string Name1;
public Class1(string subclassName2)
{
// Subclass has passed its Name2 here
}
}
public class Class2: class1 {
private string Name2;
public Class2(string myName) : base(myName) {
Name2 = myName;
}
}
You can access the code in the derived class from the base class code, but only from within an object which is actually a derived class object, and then only if the methods involved are virtual methods.
If you have an object which is itself an instance of the base class, then from within that instance you cannot see derived class code from the base class .
example
public class Baseclass{
public void Foo()
{
Bar();
}
public virtual void Bar()
{
print("I'm a BaseClass");}}
public classs Derived: BaseClass{
public override void Bar()
{
print("I'm a Derived Class");}}
Main()
var b = new BaseClass();
x.Foo() // prints "I'm a BaseClass"
// This Foo() calls Bar() in base class
var d = new Derived();
d.Foo() // prints "I'm a Derived Class"
// in above, the code for Foo() (in BaseClass)
// is accessing Bar() in derived class
I think you could not because when you instantiate derived class, base class constructor is called first to initialize base class and then the derived class is initialized.Within the base class constructor there is no way to access derived class members because they are not available at that time.
You cannot do it. It strictly violates the Object Oriented Approach programming ground rules.
As each instance of Class2 will have the Name2 property. But the same cannot be guaranteed for instance of object for Class1.
It's not really clear what you're trying to achieve. It is possible to do the following, but I don't think it's good practice:
interface IHasName2
{
string Name2 { get; }
}
class Class1
{
string Name1;
public Class1()
{
var withName2 = this as IHasName2;
if (withName2 != null)
{
Name1 = withName2.Name2;
}
}
}
Then classes deriving from Class1 may implement IHasName2 if they like.
But maybe you want an abstract class to make sure derived classes specify a Name2. It could be like this:
abstract class Class1
{
string Name1;
// instance property required to be implemented by deriving classes
protected abstract string Name2 { get; }
// instance constructor
protected Class1()
{
// 'Name2' can be read already here (dangerous?)
Name1 = Name2;
}
}
Finally, consider the simple solution proposed by dasblinkenlight to have the instance constructors of Class1 take in a string parameter for the name. Deriving classes would then have to supply that name parameter when they "chain" their base class constructor.
Related
My question may be complicated , but I will try to explain it . Suppose that I have a Interface called IA and class called A ,
Interface IA:
public interface IA
{
public void Test();
}
Class A
public class A : IA
{
public string Name { get; set; }
public A()
{
}
}
When I'm trying to use Dependency injection :
Main Class :
public class MainClass
{
IA objectA = new A();
objectA.Name = "test A"; // Not working , I didn't get this Name and I can't find it .
}
IA does not contains a definition for Name ...
What's the reason of this problem?
I have created a Gist https://gist.github.com/ian-bowyer/f1a57a5fc8e4df41cc63d9816276d708 with the code on.
I changed IA to IApple and A to Apple.
The reason is that you have created an variable of type IApple (which then does not have the Name Property in it)
IA objectA = new A();
This says create me a variable called objectA of this interface IA using the constructor A(). The objectA will have the shape of the interface (IA) and not your A (object).
If you are wanting to have Name using the code then perhaps add it to the interface to make it available.
Why do you create a Instance of interface class?
Try to create Instance of Class A like:
public class MainClass
{
A objectA = new A();
objectA.Name = "test A";
}
So you can get your Test() Method and Name Property.
Or you put Name Property in Interface Class IA and all classes inherited from this Interface have Name Property.
My base class has a method to serialize itself that I want derived classes to use.
public abstract class Base
{
public int Property1 { get; set; }
public virtual string Serialize()
{
...
return System.Text.Json.JsonSerializer.Serialize(this, jsonSerializerOptions);
}
}
The problem is that "this" in the base classes refers to the base class. When calling Serialize() from derived classes, only the properties of the base class are serialized. What can I use instead of "this" to pass to the Json serializer so that it will refer to the instance of the derived class.
Derived class may look like this:
public class Derived : Base
{
public int Property2 { get; set; }
}
I then call the Serialize() method like this:
Derived derived = new Derived();
string json = derived.Serialize();
Only Property1 is serialized.
The reason of it serialize Property1 only is you didn't override the virtual method in the derived class, So it works only for property1.
Sample:
public abstract class Base
{
public int Property1 { get; set; } = 20;
public virtual void Display()
{
MessageBox.Show(Property1.ToString());
}
}
public class Derived : Base
{
public int Property2 { get; set; } = 9;
public override void Display() //without this you can't achieve what you want
{
base.Display();
MessageBox.Show(Property2.ToString());
}
}
public class Test
{
public void ShowResult()
{
Derived derived = new Derived();
derived.Display();
}
}
Test test = new Test();
{
test.ShowResult();
}
OUTPUT
Two Messageboxes
First displays: 20
Second displays: 9
If I didn't override the virtual method in the derived class the OUTPUT would be:
One Messageboxe ONLY
Displays: 20
From Documentation
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
we can't change 'this' behavior, but you can try below solution, its work like what you need
class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
Console.WriteLine(d.Serialize());
Console.ReadLine();
}
}
public abstract class Base
{
public int Property1 { get; set; }
}
public class Derived : Base
{
public int Property2 { get; set; }
}
public static class Extensions
{
public static string Serialize(this Base obj)
{
return System.Text.Json.JsonSerializer.Serialize((object)obj);
}
}
The overload method you are using is Serialize< BaseClass >(this, options). This when called from the base class always pass the BaseType as T.
Fortunately, JsonSerializer provides another overload which you can use from baseclass and achieve the desired behavior without overriding in derived class. For this, You should be using Serialize(this,this.GetType(),options). this.GetType() wil always returns the instance type even when call is done from a base class.
This question already has answers here:
When and why would you seal a class?
(5 answers)
Closed 2 years ago.
I know that you can not inherit from a class once sealed is used but I am confused what is the difference between these two: private and sealed?
Can't we make the base class members private if we don't want to inherit them instead of the whole class? What is the point of using sealed class?
private: private limits the visiblity to a scope. Declaring a private class within a class means that sub-class can't be seen from outside of the class.
This is also true for methods and properties - they can be seen within the class, but not to any consumers or inheritors.
private keyword is used for declaring class.
sealed: If a class is declared as sealed, that means that you cannot inherit from the class. sealed class can be used when a class is internal to the operation of the library, class or why you do not want that class to be overridden because it may affect the functionality.
sealed keyword is used for declaring class
example
public class Parent {
// some thing at here
private readonly SubClass sc;
// ctor
public Parent () {
sc = new SubClass();
}
public string foo () {
return sc.bar();
}
private class SubClass {
// have some thing here
public string bar() {
//..............
return "...........";
}
}
}
You need to understand difference between inheritability and accessibility.
If you want to make your class non-inheritable, making it sealed is the best option. Also a class can not be protected, private or internal protected. Only sub class can have those access specifiers. A normal class which is directly under a namespace can only be public or internal.
Now coming to you point of making all the members private in the base class. Doing that does not serve any purpose.
You inherit a class only to reuse certain properties and/or method or override them in the inherited class. If you make all the members private in the base class you won't be able access them outside even using the object of base class.
Then what's the point of having them in the base class.
public class MyClass
{
private void MyMethod() //You can not inherit this method but you can not use it using 'MyClass' also.
{
//Some code.
}
}
MyClass myObj = new MyClass();
myObj.MyMethod(); // You can not do this as the method is private.
Now if you inherit this class in another class
public ChildClass : MyClass
{
public void ChildMethod()
{
// Some Logic
}
}
Now when you do
MyClass obj = new ChildClass();
You can not do
obj.MyMethod(); //coz this is private method.
You can not do following too.
obj.ChildMethod(); //coz that method is not known to MyClass.
So if you are making members private just for the sake of making them not available for inheritance, you are losing their accessibility from the base class too.
Understood your confusion,
First of all there is no independent private class inside a namespace, compiler throws an error.
If you make a method void m1() private inside public class A, then the method m1 is not accessible from public class B.
Sealed classes are accessible to other classes though it stops inheritance, meaning you cannot use it to derive from.
In the example below, you wont be able to access the method privatemethod from the Main(), but sealed class and sealed method can be accessed. So sealed can be accessed though cannot be inherited, that's the difference.
namespace ConsoleApp1
{
using System;
public class A
{
public virtual void test()
{
Console.WriteLine("Class A");
}
}
public class C
{
public void testSealFromOutsideClass()
{
B instanceB = new B();
instanceB.test();
}
}
public sealed class B : A
{
public override void test()
{
Console.WriteLine("Class B");
}
private void Privatemethod()
{
Console.WriteLine("Printing from a private method");
}
}
//public class C : B {}
public class TestSealedClass
{
public static void Main()
{
A a = new B();
a.test();
C c = new C();
c.testSealFromOutsideClass();
B b = new B();
Console.Read();
}
}
}
I have a desing question. Lets say I have a base class, and many derived classes.
class MyBase
{
MyBase()
{
Record();
}
void Record()
{
/// this line is able to handle every object
Recorder.Process(this);
}
}
class DerivedA : MyBase
{
public int SpecialPropertyOfA { get; set; }
DerivedA(int specialPropertyOfA)
{
SpecialPropertyOfA = specialPropertyOfA;
}
}
class DerivedB : MyBase
{
public string SpecialPropertyOfB { get; set; }
DerivedA(string specialPropertyOfB)
{
SpecialPropertyOfB = specialPropertyOfB;
}
}
As you may deduce, I want to record derived classes with all their properties set. But the above example cannot record the special properties of derived classes since they are not set when the Record method called.
One way to overcome this is to make Record method protected and call it as the last line of derived classes constructors. But this violates my base principals(every derived class should be recorded right after initialization). I want to make this mandotory by design.
Any ways to handle this?
Take a look again at what you're trying to do.
Remember that base class constructor is called before the derived class's constructor.
MyBase()
{
Record();
}
void Record()
{
Recorder.Process(this); // <-- What is "this" ?
}
What would be the value of this at this point?
The instance has not been constructed yet, the derived class's constructor hasn't event been called so there's no reference to this, hence, you can't use it here.
You'll have to call this method after the instance has been fully constructed.
A way to overcome this is using a factory method:
public static class MyBaseFactory
{
public static MyBase CreateDerivedA()
{
int specialPropertyOfA = // ...
MyBase instance = new DerivedA(specialPropertyOfA);
Recorder.Process(instance);
return instance;
}
public static MyBase CreateDerivedB()
{
string specialPropertyOfB = // ...
MyBase instance = new DerivedB(specialPropertyOfA);
Recorder.Process(instance);
return instance;
}
}
When a child class inherits from both a parent class and an interface, why can the child class not access a parent class method?
Consider the following, where I can't access the DoSomething() method.
class Program
{
static void Main(string[] args)
{
IMyInterface myClass = null;
myClass = new ChildClass();
// this returns error
myClass.DoSomething();
}
}
internal class ParentClass
{
public ParentClass() { }
public void DoSomething() { }
}
internal class ChildClass : ParentClass, IMyInterface
{
public string MyProperty { get; set; }
public ChildClass() : base() { }
}
internal interface IMyInterface
{
string MyProperty { get; set; }
}
I've looked through SO discussions here and here, but they seem to focus on how a member is hidden using new, override, and virtual keywords... sorry, but I can't figure out how that applies to this situation. Also, I've browsed through the MSDN API reference on interfaces here and here, with no luck.
The problem here is specifically to do with the declaration of the variable in your Main method.
IMyInterface myClass = null;
myClass = new ChildClass();
// this returns error
myClass.DoSomething();
Taking lines in isolation, we can reduce it to just this.
IMyInterface myClass = null;
// BLAH BLAH myClass gets initialized somehow, we don't know/care how.
myClass.DoSomething();
So at that point, we only know we have an initialized object of interface IMyInterface. In other words, taking that line alone, we don't know that it's a ChildClass. The only known method of IMyInterface is MyProperty, so that's the only thing we know is available to us.
You could fix this by declaring myClass specifically as a ChildClass instance. You can even return this variable in a method that expects to return an IMyInterface type.
This does not work for a very straightforward reason:
IMyInterface does not have a DoSomething method.
If you modify your interface as follows, your code will work.
internal interface IMyInterface
{
string MyProperty { get; set; }
void DoSomething();
}
DoSomething() is from ParentClass, and you are using an IMyInterface reference.
To use this method, you need to do a cast:
((ChildClass) myClass).DoSomething();
or
((ParentClass) myClass).DoSomething();
Because the type of myClass is IMyInterface:
IMyInterface myClass = null;
and IMyInterface doesn't have a DoSomething() method:
internal interface IMyInterface
{
string MyProperty { get; set; }
}
However, with polymorphism the type cal also be ParentClass or ChildClass. So you can use the method by morphing the type:
(myClass as ChildClass).DoSomething();
As with any time you cast or morph the type of an object, be careful for nulls. If the type can't be converted then myClass as ChildClass would be null, so the above would result in a NullReferenceException.
The best way to understand this is to know the difference between an interface and a parent/child class.
An interface is a contract that can exist on any class regardless of it's inheritance chain. You could put that interface on a class that doesn't inherit from ParentClass, and all that class has to fulfill is what is in your interface (in your case, the MyProperty property). If you added DoSomething() to the interface, this class would then also be required to have that method.
A subclass (child class) inheriting from a parent class has established a relationship. The parent class shares it's non-private methods/properties/member subset with it's child class. Therefore, you can cast a child class to it's parent class and retain accessibility to those properties.