I'm having a few issues while trying use Inheritance. I create a class named vehicle with some properties, and the another one named car which inherits the properties from vehicle, them when I run the code below, the C# compiler returns the following error:
Program.cs (38,13): error CS0246: The namespace name or type 'car' could not be found. Need a policy using or an assembly reference?
Here's the code:
using System;
class vehicle
{
public int MaxSpeed;
public bool turnOn;
public int wheels;
public void car_on()
{
turnOn = true;
}
public void car_off()
{
turnOn = false;
}
class car : vehicle
{
public string name;
public string color;
public car(string name, string color)
{
this.name = name;
this.color = color;
MaxSpeed = 220;
wheels = 4;
turnOn();
}
}
}
namespace Aula_28_herança
{
class Program
{
static void Main(string[] args)
{
car c1= new car("ferrari","red");
Console.WriteLine("Nome................:{0}", c1.name);
Console.WriteLine("Cor.................:{0}", c1.color;
Console.WriteLine("Velociade Máxima....:{0}", c1.MaxSpeed);
Console.WriteLine("Quantiadade de Rodas:{0}", c1.wheels);
Console.WriteLine("Status..............:{0}", c1.turnOn);
}
}
}
You need to make your carro type public:
class veiculo{
....
public class carro : veiculo{
...
}
}
Ad use veiculo.carro for type:
veiculo.carro c1= new veiculo.carro("ferrari","vermelha");
See the docs on Nested Types:
Regardless of whether the outer type is a class, interface, or struct, nested types default to private; they are accessible only from their containing type.
Related
using System;
namespace AssemblyOne
{
public class AssemblyOneClassOne
{
protected internal int ID = 101;
public int id = 102;
public void Print()
{
Console.WriteLine("Abdullah is a handsome hunk!");
}
}
public class AssemblyOneClassTwo
{
public void SampleMethod()
{
AssemblyOneClassOne a1 = new AssemblyOneClassOne();
Console.WriteLine(a1.ID);
}
}
public class A
{
public static void Main()
{
AssemblyOneClassTwo a2 = new AssemblyOneClassTwo();
a2.SampleMethod();
Console.ReadKey();
}
}
}
using System;
using AssemblyOne;
namespace AssemblyTwo
{
public class AssemblyTwoClassOne
{
AssemblyOneClassOne instance = new AssemblyOneClassOne();
instance.Print();//Over here I am getting compile time error, 'instance' does not exist in the current context, 'instance.Print' does not exist in the current context
}
}
As far as I know, public types can be accessed in anywhere in the same assembly as well as in another assembly
Yes, public types can be accessed from another assembly but your method Print() should be called inside a method of class AssemblyTwoClassOne.
Something like this -
namespace AssemblyTwo
{
public class AssemblyTwoClassOne
{
AssemblyOneClassOne instance = new();
public void Method() => instance.Print();
}
}
I'm learning OOAD and trying to implement class relationship with inheritance but there is an issue here is the code
Parent Class
namespace ConsoleApplication1
{
abstract class Classification
{
public abstract string type();
}
}
1st Child Class
namespace ConsoleApplication1
{
class FullTime : Classification
{
bool inCampus;
string roomDetail;
float rent;
public FullTime(string studentRoomDetail, float studentRent)
{
this.inCampus = true;
this.roomDetail = studentRoomDetail;
this.rent = studentRent;
}
public FullTime()
{
this.inCampus = false;
}
public string printAccommodationDescription()
{
if (!this.inCampus)
{
return "Not in campus";
}
else
{
return "Room: " + this.roomDetail + " Rent: " + this.rent.ToString();
}
}
public override string type()
{
return "fulltime";
}
}
}
2nd Child Class
namespace ConsoleApplication1
{
class PartTime : Classification
{
bool onJob;
string jobTitle;
float salary;
public PartTime(string studentJobTitle, float studentSalary)
{
this.onJob = true;
this.jobTitle = studentJobTitle;
this.salary = studentSalary;
}
public PartTime()
{
this.onJob = false;
}
public string printJobDescription()
{
if (!this.onJob)
{
return "Not on job";
}
else
{
return "JobTitle: " + this.jobTitle + " Salary: " + this.salary.ToString();
}
}
public override string type()
{
return "parttime";
}
}
}
Now in Program.cs when I tried to access method printJobDescription from PartTime class
Classification classification = new PartTime("Software Engineer", 10000);
classification.printJobDescription();
it says
Error CS1061 'Classification' does not contain a definition for 'printAccommodationDescription' and no extension method 'printAccommodationDescription' accepting a first argument of type 'Classification' could be found (are you missing a using directive or an assembly reference?)
How can I solve this issue?
UPDATE
I need the ability to let object change its class at runtime, so I have to create the object of type Classification and use either method that is not implemented in other class
You can only use the functions declared in the class you use.
abstract class Classification
{
public abstract string type();
}
class PartTime : Classification
{
public override string type() {...}
public Job1() {...}
}
class FullTime : Classification
{
public override string type() {...}
public Job2() {...}
}
A object of type Classification can only use the type()
A object of the type PartTime can use type and Job1()
A object of the type FullTime can use type and Job2()
If you have an object like this:
Classification classification = new PartTime();
and you don´t know which special type, you have to cast this object to use other methods:
if (classification is PartTime)
{
((PartTime)classification).Job1();
}
else if (classification is FullTime)
{
((FullTime)classification).Job2();
}
Hope this helps.
When casting you're object into another object type, that called Polymorphism. This translate that you can only use the methods and properties that exposed to the destination object type, which is Classification which doesn't know your method.
Simple example i made:
using System;
namespace Program
{
public class Program
{
public static void Main()
{
Dog rex = new Dog();
Animal rexAsAnimal = rex;
// Can access 'MakeSound' due the fact it declared at Dog (Inherited by Animal)
Console.WriteLine(rex.MakeSound()); // Output: Bark
// Compilation error: rexAsAnimal is defined as 'Animal' which doesn't have the 'Bark' method.
//Console.WriteLine(rexAsAnimal.Bark()); // Output when uncomment: Compilation error.
// Explicitly telling the compiler to cast the object into "Dog"
Console.WriteLine(((Dog)rexAsAnimal).Bark()); // Output: Bark
}
}
public abstract class Animal
{
public abstract string MakeSound();
}
public class Dog : Animal
{
public override string MakeSound() { return Bark(); }
public string Bark()
{
return "Bark";
}
}
}
I've got a base class and three subtypes that derive from that class (see example below).
public abstract class Vehicle
{
string name;
string color;
}
public class Car : Vehicle
{
int nrofwheels;
}
public class Train : Vehicle
{
int nrofrailcars;
}
To make one of my method as generic as possible, I'd like to pass the base type as parameter and then detect hat subtype it is inside my method like this:
public static void main(string[] args)
{
public Car c = new Car();
public Train t = new Train();
public CheckType(Vehicle v)
{
if(v.GetType()==typeof(Car)) Console.Write(v.nrofwheels);
else Console.Write(v.nrofrailcars);
}
}
This doesn't seem to work, why and what else can I try?
[edit] I know that the class examples aren't complete, but I'd figured that its not necessary for this purpose.
You should refactor that class and move CheckType to Vehicle class and override it in descendant classes. And CheckType name is not the best one, it makes no sense since that method returns number of wheels / rails.
Something like this:
public abstract class Vehicle
{
string name;
string color;
public abstract int CheckType();
}
public class Car : Vehicle
{
int nrofwheels;
public override int CheckType()
{
return this.nrofwheels;
}
}
public class Train : Vehicle
{
int nrofrailcars;
public override int CheckType()
{
return this.nrofrailcars;
}
}
You can use as. You forgot to cast the object to make the properties accessible:
public CheckType(Vehicle v)
{
Train t = v as Train;
if (t != null)
Console.Write(t.nrofrailcars);
else
{
Car c = v as Car;
if (c != null)
Console.Write(c.nrofwheels);
}
}
I am trying to create a base class in c# that I can extend out to sub classes.
For example:
public class ObjectsInTheSky
{
public string Size, Shape;
public float Mass;
public int DistanceFromEarth;
public bool hasAtmosphere, hasLife;
public enum ObjectTypes {Planets,Stars,Moons}
public ObjectsInTheSky( int id )
{
this.Load( id );
}
public void Load( int id)
{
DataTable table = Get.DataTable.From.DataBase(id);
System.Reflection.PropertyInfo[] propInfo = this.GetType().GetProperties();
Type tp = this.GetType();
foreach (System.Reflection.PropertyInfo info in propInfo)
{
PropertyInfo p = tp.GetProperty(info.Name);
try
{
if (info.PropertyType.Name == "String")
{
p.SetValue(this, table.Rows[0][info.Name].ToString(), null);
}
else if (info.PropertyType.Name == "DateTime")
{
p.SetValue(this, (DateTime)table.Rows[0][info.Name], null);
}
else
{
p.SetValue(this, Convert.ToInt32(table.Rows[0][info.Name]), null);
}
}
catch (Exception e)
{
Console.Write(e.ToString());
}
}
}
}
public class Planets : ObjectsInTheSky
{
public Moons[] moons;
}
public class Moons : ObjectsInTheSky
{
}
public class Stars : ObjectsInTheSky
{
public StarTypes type;
public enum StarTypes {Binary,Pulsar,RedGiant}
}
My problem is when I try to use an object:
Stars star = new Stars(142);
star.type does not exists and property of star, it exists as star.star.type but completely inaccessable, or I can not figure out how to access it.
I do not know if I'm extending the ObjectsInTheSky property properly or not. Any help or pointers will be greatly appreciated.
It looks as though you are trying to use a constructor that is not defined on your subclass Stars or the base class.
Stars star = new Stars(142);
If you are trying to use the .Load(int) method then you would need to do this:
Stars star = new Stars();
star.Load(142);
Or, if you are trying to use the base constructor, you need to define it in the subclass:
public class Stars : ObjectsInTheSky
{
public Stars(int id) : base(id) // base class's constructor passing in the id value
{
}
public Stars() // in order to not break the code above
{
}
public StarTypes type;
public enum StarTypes {Binary,Pulsar,RedGiant}
}
Constructors in C# are not inherited. You need to add the additional constructor overloads to each of the base classes:
public class Stars : ObjectsInTheSky
{
public Stars(int id) : base(id) { }
public StarTypes type;
public enum StarTypes {Binary,Pulsar,RedGiant}
}
This will create a constructor that just calls the base class's constructor for you.
Without any code in the subclasses, I'd like an abstract class to have a different copy of a static variable for each subclass. In C#
abstract class ClassA
{
static string theValue;
// just to demonstrate
public string GetValue()
{
return theValue;
}
...
}
class ClassB : ClassA { }
class ClassC : ClassA { }
and (for example):
(new ClassB()).GetValue(); // returns "Banana"
(new ClassC()).GetValue(); // returns "Coconut"
My current solution is this:
abstract class ClassA
{
static Dictionary<Type, string> theValue;
public string GetValue()
{
return theValue[this.GetType()];
}
...
}
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
This is similar to Can I have different copies of a static variable for each different type of inheriting class, but I have no control over the subclasses
There is a more elegant way. You can exploit the fact that statics in a generic base class are different for each derived class of a different type
public abstract class BaseClass<T> where T : class
{
public static int x = 6;
public int MyProperty { get => x; set => x = value; }
}
For each child class, the static int x will be unique for each unique T
Lets derive two child classes, and we use the name of the child class as the generic T in the base class.
public class ChildA: BaseClass<ChildA>
{
}
public class ChildB : BaseClass<ChildB>
{
}
Now the static MyProperty is unique for both ChildA and ChildB
var TA = new ChildA();
TA.MyProperty = 8;
var TB = new ChildB();
TB.MyProperty = 4;
While this works fine, I'm wondering if there's a more elegant or built-in way of doing this?
There isn't really a built-in way of doing this, as you're kind of violating basic OO principles here. Your base class should have no knowledge of subclasses in traditional object oriented theory.
That being said, if you must do this, your implementation is probably about as good as you're going to get, unless you can add some other info to the subclasses directly. If you need to control this, and you can't change subclasses, this will probably be your best approach.
This is a little different than what you're asking for, but perhaps accomplishes the same thing.
class Program
{
static void Main(string[] args)
{
Console.WriteLine((new B()).theValue);
Console.WriteLine((new C()).theValue);
Console.ReadKey();
}
}
public abstract class A
{
public readonly string theValue;
protected A(string s)
{
theValue = s;
}
}
public class B : A
{
public B(): base("Banana")
{
}
}
public class C : A
{
public C(): base("Coconut")
{
}
}
There's an alternative solution which might or might not be better than yours, depending on the use case:
abstract class ClassA
{
private static class InternalClass<T> {
public static string Value;
}
public string GetValue()
{
return (string)typeof(InternalClass<>)
.MakeGenericType(GetType())
.GetField("Value", BindingFlags.Public | BindingFlags.Static)
.GetValue(null);
}
}
This approach is used in EqualityComparer<T>.Default. Of course, it's not used for this problem. You should really consider making GetValue abstract and override it in each derived class.
What about this?
class Base {
protected static SomeObjectType myVariable;
protected void doSomething()
{
Console.WriteLine( myVariable.SomeProperty );
}
}
class AAA : Base
{
static AAA()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "A";
}
}
class BBB : Base
{
static BBB()
{
myVariable = new SomeObjectType();
myVariable.SomeProperty = "B";
}
}
It works for me.
Would be even nicer with Interface.
Simple solution: just use word "new".
public abstract class AbstractClass
{
public static int Variable;
}
public class RealizationA : AbstractClass
{
public new static int Variable;
}
public class RealizationB : AbstractClass
{
public new static int Variable;
}
And the result:
AbstractClass.Variable = 1;
RealizationA.Variable = 2;
RealizationB.Variable = 3;
Console.WriteLine(AbstractClass.Variable); //1
Console.WriteLine(RealizationA.Variable); //2
Console.WriteLine(RealizationB.Variable); //3
or you can use property:
//in abstract class
public static int Variable {get; set;}
//in child class
public static new int Variable {get; set;}
or function (but remember to add "new" to both variable and function):
//in abstract class
protected static int Variable;
public static int GetVariable() { return Variable; }
public static void SetVariable(int v) { Variable = v; }
//in child class
protected new static int Variable;
public static new int GetVariable() { return Variable; }
public static new void SetVariable(int v) { Variable = v; }
or you can use private variables (you don't need to use "new") with functions to get and set:
//in abstract class
private static int Variable;
//get and set methods
//in child class
private static int Variable;
//get and set methods