This is probably a simple thing to fix. I'm a university student and we just started polymorphism, so the concept is still puzzling to me.
abstract class IncreaseTransaction
{
private string _Description;
private decimal _Amount;
protected IncreaseTransaction(string description, decimal amount)
{
_Description = description;
_Amount = amount;
}
}
class Deposit : IncreaseTransaction
{
public Deposit(string description, decimal amount) : base("Deposit", amount)
{
}
}
static void Main(string[] args)
{
Customer fred = new Customer("Fred");
SavingsAccount fredSavings = new SavingsAccount();
fredSavings.AddTransaction(new Deposit(500.00M));
}
When a new deposit is instantiated, I want the literal string "Deposit" to be used as the description for the transaction. However, I'm getting an error stating 'SampleNamespace.Deposit does not contain a constructor that takes one argument'. So, the string is not being inherited, and I am unsure how to fix this. I would greatly appreciate any help!
Your constructor for Deposit takes two parameters:
public Deposit(string description, decimal amount) : base("Deposit", amount)
Since you're setting "Deposit" in the call to base(), you don't need 'string description' in that constructor. It should look like:
public Deposit(decimal amount) : base("Deposit", amount)
The following line should no longer throw an error:
fredSavings.AddTransaction(new Deposit(500.00M));
Additional Explanation: Constructors are not inherited like members or properties, but are unique to both the child and parent. The child (Deposit) has to invoke the base class's (IncreaseTransaction) constructor, but it does not need to require the same parameters in its own constructor.
Here is an old (but good) discussion of why this is the case: Why are constructors not inherited?
Related
I have a code that uses inheritance in C# and I seem to have lost my price variable along the way. How can I get my price variable to work with the child classes when the parent class doesn't have it as a parameter? Please note: this has been submitted and marked, I'm not looking for extra marks, just trying to improve my learning.
Not sure if this is enough code to help, but I didn't want to flood the screen. Basically the PerformBuyStock method is in the program file and it records the price variable along with the quantity. However once the transaction is executed through the transaction class, because it doesn't have 3 parameters (stock, price, quantity) like the StockPurchaseTransaction class, then the price reverts to 0 when it executes printSummary. How do I get the price variable to still be there without changing the Transaction class? Thank you for any help you may be able to provide.
public abstract class Transaction
{
protected readonly Stock _stock;
protected readonly decimal _price;
protected readonly int _quantity;
protected readonly string SummaryLine;
public Transaction(Stock stock, int quantity)
{
_quantity = quantity;
_stock = stock;
SummaryLine = ($" - {_stock.Name} x {_quantity} #${_price}");
}
}
public class StockPurchaseTransaction : Transaction
{
public StockPurchaseTransaction(Stock stock, decimal price, int quantity) :base(stock, quantity)
{
stock = _stock;
price = _price;
quantity = _quantity;
}
public override void PrintSummary()
{
Console.WriteLine($"BUY {SummaryLine}");
}
}
private static void PerformBuyStock(Warehouse toWarehouse)
{
Stock stock = FindStockItem(toWarehouse);
if (stock == null) return;
int quantity;
decimal price;
Console.WriteLine($"Quantity of {stock.Name} purchased:");
quantity = Convert.ToInt32(Console.ReadLine());
Console.WriteLine($"Price per item purchased: ");
price = Convert.ToDecimal(Console.ReadLine());
StockPurchaseTransaction purchase;
purchase = new StockPurchaseTransaction(stock, price, quantity);
toWarehouse.ExecuteTransaction(purchase);
purchase.PrintSummary();
}
public void ExecuteTransaction(Transaction transaction)
{
_transactions.Add(transaction);
transaction.Execute();
}
the price reverts to 0 when it executes printSummary. How do I get the price variable to still be there without changing the Transaction class?
The issue is that the base class constructor is what sets the SummaryLine field, which is used to print the summary later. But at the time that that field is set, the _price field hasn't been initialized to the caller-provided value (indeed, it never is). It still has the default value of 0.
It certainly doesn't help that in the subclass constructor, you aren't even assigning the field correctly. The variables are on the wrong side of each assignment operator. As it happens, if you'd put them on the correct side, you'd have gotten a helpful compile-time error message explaining that the subclass constructor isn't allowed to assign a value to the readonly fields in the base class.
Anyway…
To fix it without changing the Transaction class? Well, the only way to do that is to add code in your subclass StockPurchaseTransaction that mirrors the code in the base class, but fixes the bugs that exist in it.
That might look something like this:
public StockPurchaseTransaction(Stock stock, decimal price, int quantity) :base(stock, quantity)
{
// To be clear: these three assignments are incorrect, and accomplish nothing
stock = _stock;
price = _price;
quantity = _quantity;
// This assignment would "fix" the problem, but it's not really the right way,
// and the field is readonly so this won't actually compile
SummaryLine = ($" - {stock.Name} x {quantity} #${price}");
}
Except that won't work, because unlike the assignments before it, the correct assignment of SummaryLine won't work as long as the base class field is readonly.
But really, the base class constructor is what's wrong, and that's where the fix ought to go:
public Transaction(Stock stock, int quantity, decimal price)
{
_quantity = quantity;
_stock = stock;
_price = price;
SummaryLine = ($" - {_stock.Name} x {_quantity} #${_price}");
}
Of course, then you'd need to add the price parameter to the base class constructor call:
public StockPurchaseTransaction(Stock stock, decimal price, int quantity)
: base(stock, quantity, price) { }
Note that if you do it that way, then the subclass constructor has nothing to do. All of the real work is done in the base class.
Bottom line, it's impossible to do what you are literally asking. The base class has bugs in it, and because of the readonly fields, you can't correct for those bugs in the subclass. They have to be fixed in the base class.
I am curious to know what is the proper way of writing a constructor or rather when do I write it this way or the other.
I would also like to know why would you change the name of the field in the construcor, like I did in the first constructor with the field address.
Thank you for your help.
For example lets say you have a class Shipment with four fields: String item, Double price, String address, Double weight.
class Shipment
{
private string item;
private double price;
private string address;
private double weight;
public Shipment(string item, double price, string addr, double weight)
{
this.item=item;
this.price=price;
address=addr;
this.weight=weight;
}
public Shipment()
{
item="Football jersey";
price=35.99;
address="8520 Washington Dr.Toledo, OH 43612"
weight=0.400;
}
}
I would change the default constructor definition like this,
public Shipment : this ("Football jersey", 35.99, "8520 Washington Dr.Toledo, OH 43612", 0.400 )
{
}
This reuses the parameterized constructor and makes your code a bit more concise.
The rest of your code is ok. The usage of this in the constructor is pretty standard and it prevents you from inventing other names for the constructor arguments (ex - addressParams).
Who ya gonna call?
Unrelated code to pose the problem. Not the best editor tool so being terse. Thanks.
A new method that is part of the derived class cannot be accessed by the new
object. All the Intellisense sees are the abstract parts of the base class. Typing them in and running them gets an error. If methods and fields can't be added what is the point of base to derived and on down. I have searched all examples and come up empty.
public class SalesEmployee : Employee
{
public decimal salesbonus; // Additional field
public SalesEmployee(string name, decimal basepay, decimal salesbonus)
{
this.salesbonus = salesbonus; // Create new field
}
public override decimal CalculatePay() // Override abstract
{
return basepay + salesbonus;
}
public decimal CalculateExtraBonus() // Not an override
{
return basepay + (0.5 * salesbonus); // Belongs to this class only
}
}
static void Main()
{
// Create new employee.
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
decimal = employee1.CalculateExtraBonus(); // Can't see the new method
// Derived class cannot get to new method.
}
I'm thinking of trying the following. Typing out questions really helps.
{ SalesEmployee salesEmpInstance = employee1
decimal = salesEmpInstance.CalculateExtraBonus()
// Maybe this could see the method.
I'll ignore the syntax errors and assume you have it right in your actual code. However it looks like you forgot to call the parents constructor ("base") on your derived class constructor and then tried to access a variable only instantiated by the parent. Also you need to cast the literal "0.5" as a decimal.
You can read more about "base" on msdn
Working code is below. Output is 1250.
using System;
public abstract class Employee
{
public string name;
public decimal basepay;
public Employee(string name, decimal basepay)
{
this.name = name;
this.basepay = basepay;
}
public abstract decimal CalculatePay();
}
public class SalesEmployee : Employee
{
public decimal salesbonus; // Additional field
// -->ERROR HERE, You forgot to call the base and instantiate
// the fields of the parent.
public SalesEmployee(string name, decimal basepay, decimal salesbonus): base(name, basepay)
{
this.salesbonus = salesbonus; // Create new field
}
public override decimal CalculatePay() // Override abstract
{
return basepay + salesbonus;
}
public decimal CalculateExtraBonus() // Not an override
{
return basepay + ((decimal)0.5 * salesbonus); // Belongs to this class only
}
}
class Program
{
static void Main(string[] args)
{
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
decimal aliceBonus = employee1.CalculateExtraBonus();
Console.WriteLine(aliceBonus);
}
}
Your code looks fine, I recommend you:
Remove the reference to the first class library from your new project.
Rebuild your first class library
Reference again the first class library dll file in your new project, maybe you referenced to an older version of the dll. You should reference to the last created dll of first class library
Correct your code like this
.
{
SalesEmployee employee1 = new SalesEmployee("Alice", 1000, 500);
SalesEmployee salesEmpInstance = employee1 ;
decimal result = salesEmpInstance.CalculateExtraBonus();
}
Anyway if you have not any reference in this case. Compair the following codes with your code. I tested it. It works...
Note1: You should use base in your constructor to pass name and basepay to their corresponding fields in base class.
Note2: Now Rebuild your project, have you any error? I have not! Have you VS Intellisense problem yet?
Can some one tell me how to define the class Student such that the last test case is satisfied.
I could not understand how the method implementation of last function GetId().
public const int basicId = 12345;
public const int studentId = 88888;
public const string sampleName = "User Name";
[TestMethod]
public void StudentIsInitializedCorrectly()
{
User student = new Student(sampleName, basicId, studentId);
Assert.AreEqual(sampleName, student.GetName());
Assert.AreEqual(basicId, student.GetId());
Assert.AreEqual(studentId, ((Student)student).GetId());
}
Thanks
I understand from the comments that you are working through some test-driven-development (TDD) exercises, and that you are having trouble understanding this example. So with that in mind, here's how I look at it:
The first thing that happens in the test is that while you are creating an instance of Student, it is being assigned to a variable that has the type User. There are different ways that this could work, but the most obvious explanation is that User is the base class, and that Student inherits User.
The next two statements call methods on the student variable directly. Since the type of this variable is User, those methods must exist in the User class. Again there are multiple ways that this could actually work, but the simplest is to assume that the values those methods need to return are in fact stored in the User class.
Those two points lead us to a User class that looks something like this:
class User
{
private readonly string _name;
private readonly int _id;
public User(string name, int id)
{
_name = name;
_id = id;
}
public string GetName() { return _name; }
public int GetId() { return _id; }
}
The above ensures that when we view the object instance through a variable having the type User, that we can still call the GetName() and GetId() methods, and get back the values we expect.
Now we come to the third and final test in the method. Note that this test casts the student variable to the class Student before calling the method. Note also that this method is expected to return the value in studentId and not the value in basicId, which is the value that the base class's GetId() method is supposed to return.
So we have the same method name, used on the same object instance, but which is supposed to behave differently depending on the compile-time type of the object (aka "static type"). This is as opposed to the run-time type, which is the actual type of the object.
Given that, we have to declare a new GetId() method in the Student class, and of course provide a way for it to return the different ID value that was used during the initialization of the object:
class Student : User
{
private readonly int _id;
public Student(string name, int basicId, int studentId)
: base(name, basicId)
{
_id = studentId;
}
public new int GetId() { return _id; }
}
The one wrinkle is that given that we already know the User class has a method with this exact same name, you will be hiding that class's method with your new GetId() method. Thus, the new keyword is required to avoid any compile-time warnings.
My personal preference is to avoid method hiding always. It is pretty much always the wrong design choice, and should be used only when forced into it by some outside requirement.
(Note that the fields in the above classes are marked readonly. There's nothing in the test that requires this to be the case, but there's also nothing in the test that prevents it. My preference is to make fields readonly unless they can't be, hence the use of readonly here).
Thanks in advance guys. I am quite new to coding so please be patient. Below is a piece of code I am working on. This is the complete code below. It's as follows:
using System;
public class Product
{
private string name;
private decimal price;
public string Name
{
get
{ return name; }
set
{ name = value; }
}
public decimal Price
{
get
{ return price; }
set
{ price = value; }
}
public Product(string name, decimal price)
{
this.name = name;
this.price = price;
}
}
In the page load method, an object is instantiated and the constructor is called as follows:
private void Page_Load(object sender, EventArgs e)
{
Product saleProduct = new Product("Kitchen Garbage", 49.99M);
}
When the product is created, the constructor is initialised, with the above values. Now if you look in the constructor, you have:
this.name = name;
and
this.price = price;
After the above two lines of code are executed, the property accessors automatically assign the private variables ("name" and "price") with the intended values.
So how are the lines:
this.name = name;
and
this.price = price;
able to call the public accessors, named "Name" and "Price"?
I have only seen when a public accessor is explicitly called such as:
saleProduct.Name = "Kitchen Garbage";
I don't understand how:
this.name = name;
and
this.price = price;
can access a private variable directly. I thought the whole point of property accessors was that you had to go via the property name in order to access the private variables such as:
saleProduct.Name = "Kitchen Garbage";
Can you help and explain how
this.name = name;
and
this.price = price;
is able to access the public properties? Even the name of the properties ie "Name" and "Price" are changed to "Kitchen Garbage" and "49.99" respectively when the above two lines of code are executed.
Also, how does
this.name = name;
and
this.price = price;
know which public accessor to call?
I have searched everywhere for an explanation but no luck.
Thank you.
The private members name and price are accessible in all non-static methods within the class Product. Since the constructor for Product is part of the class, the members are accessible there as well.
Your constructor is not using the public properties Name and Price. They retrieve their values from the corresponding private members.
this.name refers to private string name;. It's private, so only code inside the class can refer to it.
The this. prefix is only required because otherwise the code would be ambiguous, since there's a parameter called name as well.
The public accessor public string Name does not have any storage of its own. It passes through to the private field name.
The code this.name = name; does not touch the property Name - it's the other way around.
When you do this.name = name;, you are setting the value of the private field called name.
Whenever you access the public property Name, you are indirectly accessing that same field (name).
Look at the definition of the property:
get { return name; }
Note that here, name refers to the same field as this.name. You could change it to this.name and there'd be no effect. It's just not required here, since there's no ambiguity.
this.name = name;
and
this.price = price;
are used in the Constructor for the Product class. Private members are accessible from the Constructor (as well as from any non-static method on the class).
Basically, when you 'new' an object, the memory structure of the object is allocated, and then the constructor is called to allow for any initialization of that object. Making the name and price member variables private just means that you can only access them from inside the class members themselves, of which the constructor is.
The public properties Name and Price, as implemented here, are just wrappers around those private name and price variables, and allow you to do other things when setting or fetching (imagine wanting to count the number of times a value is referenced: you could increment some counter in the get{} of a public property).
in your constructor you are not setting the values via the public setter, you're setting the private backing field directly.
FYI I believe it is generally considered best practice to name class level items with an Upper letter (or underscore sometimes in the case of members/backing fields?), and function level variables and parameters with a lower letter. (Don't quote me on this paragraph :P)
so to set the field via it's setter just do:
public class Foo
{
private string _bar;
public string Bar
{
set
{
this._bar = value;
}
get
{
return _bar;
}
}
public Foo(string bar)
{
this.Bar = bar;
}
}
vs.
public Foo(string bar)
{
this._bar = bar
}
The above is equivalent to what you're doing in your code. Note with your current implementation it doesn't really make a difference, since you have no additional logic in your setter. If you did however, in your implementation you would miss out on that additional logic.
note i changed the variables around a bit to make it more obvious what's being done.
to demonstrate that point consider this:
public class Foo
private string _bar;
public string Bar
{
set
{
this._bar = value + " blah blah";
}
get
{
return _bar;
}
}
public Foo()
{
this.Bar = "test";
Console.WriteLine(Bar); // outputs "test blah blah"
this._bar = "test";
Console.WriteLine(Bar); // outputs "test"
}
}
The lower cased name and price are private 'backing' variables for the public Name and Price variables. They can only be accessed from within the class itself. The reason for using this.price is because the method is taking a param called 'price' so you need to specify that you're setting the classes field and not assigning to the local variable. You'll often see this in constructors, personally I would choose to name the arguments something different than the fields in my class and then it wouldn't be necessary.