Incorrect "Creating an instance of the Abstract class is not allowed"

8 views (last 30 days)
Hi! Trying to instantiate a derived class, query_dev, whose classdef has not a single occurrence of the word Abstract, I get the complaint "Creating an instance of the Abstract class 'query_dev' is not allowed." I've searched my Matlab path--using, separately, "query_dev" and "Abstract"--for other files that might be defining the class, and come up empty handed. Due to the nature of the problem (I guess), even setting a break point at the very first executable line of the constructor is useless (i.e., the error is returned before the break point is reached). Restarting Matlab also didn't fix.
Below is my code (minus comments), first the (Abstract) parent class, then the "problem child." Thanks for your help.
classdef SQLstatement_dev < handle
properties
conn;
tbls = {};
result = {};
issuedStatementError = false;
issuedAvailableError = false;
devVer;
end
properties (Dependent = true)
DBname;
statement;
availableTables;
availableColumns;
end
methods
function SQLobject = SQLstatement_dev(DBname, un, pwd, devVerOverride)
if nargin < 4
SQLobject.devVer = is_devVer(SQLobject);
else
SQLobject.devVer = devVerOverride;
end
if ~SQLobject.devVer
SQLobject.conn = database(DBname, un, pwd);
if ~isempty(SQLobject.conn.Message)
disp(SQLobject.conn.Message)
else
disp(['Connection to database ' SQLobject.DBname ' opened successfully!'])
end
end
end
function delete(obj)
try
close(obj.conn);
catch me
end
end
function name = get.DBname(obj)
if ~obj.devVer
name = obj.conn.Instance;
else
name = 'Development Version: database connection not established on purpose.';
end
end
function S = get.statement(obj)
try
S = obj.assembleStatement;
catch me
if obj.issuedStatementError
S = getReport(me);
obj.issuedStatementError = false;
else
disp('Sorry, attempt to assemble statement failed!')
disp('More info is in this object''s "statement" field.')
obj.issuedStatementError = true;
end
end
end
function aT = get.availableTables(obj)
try
if ~obj.devVer
tmp = fetch(exec(obj.conn, 'select Name from sys.Tables'));
aT = tmp.Data;
else
aT = {};
end
catch me
aT = getReport(me);
if obj.issuedAvailableError
obj.issuedAvailableError = false;
else
disp('Sorry, attempt to get available tables failed!')
disp('More info is in this object''s "availableTables" field.')
obj.issuedAvailableError = true;
end
end
end
function aC = get.availableColumns(obj)
aC = struct.empty;
if ~isempty(obj.tbls)
cat = get(obj.conn, 'Catalog');
sch = schemas(obj.conn, cat);
for t = obj.tbls
for s = sch
if ismember(t, tables(obj.conn, cat, s))
aC.(t) = columns(obj.conn, cat, s, t);
break;
end
end
end
end
end
function addPropVals(obj, prop, newElements)
if ismember(prop, fieldnames(obj))
obj.(prop) = extendArray(obj.(prop), newElements);
end
end
end
methods (Abstract)
S = assembleStatement(obj);
submitStatement(obj);
setPropVals(obj, prop, elements, extend);
getPropVals(obj, prop);
end
end
classdef query_dev < SQLstatement_dev
properties
columns = {};
orderBy = {};
where = '';
end
methods
function qObject = query_dev(DBname, un, pword, parameters)
if nargin < 4
parameters = struct.empty;
end
if nargin < 3
pword = '';
end
if nargin < 2
un = '';
end
if nargin < 1
DBname = '';
end
qObject = qObject@SQLstatement_dev(DBname, un, pword);
paraFields = fieldnames(parameters);
for prop={'columns', 'tables', 'orderBy', 'where'}
prop = prop{:};
if ismember(prop, paraFields)
qObject.(prop) = extendArray(qObject.(prop), parameters.(prop));
end
end
end
function errCode = setPropVals(obj, prop, elements, extend)
if nargin < 4
extend = false;
end
errCode = '';
if ~(isequal(prop, 'where') || iscell(elements))
elements = {elements};
end
switch prop
case 'where'
if ~ischar(elements)
errCode = 'query.setPropVals error: wrong type for where clause';
end
case 'tables'
if numel(elements)~=1
errCode = 'query.setPropVals error: received more than one value for tables';
elseif numel(elements)==1 && ~extend
errCode = ['query.setPropVals error: asked to make tables contain more than '...
'one element; this is not allowed in a "non-join" query'];
elseif ~ischar(elements{1})
errCode = 'query.setPropVals error: wrong type for tables';
end
case 'columns'
for i=1:length(elements)
if ~ischar(elements{i})
errCode = ['query.setPropVals error: at least one value for columns is '...
'the wrong type'];
end
end
otherwise
end
if ismember(prop, fieldnames(obj))
obj.(prop) = elements;
end
end
end
end

Accepted Answer

Pierre
Pierre on 16 Aug 2011
query_dev inherits the abstract methods
methods (Abstract)
S = assembleStatement(obj);
submitStatement(obj);
setPropVals(obj, prop, elements, extend);
getPropVals(obj, prop);
end
declared in SQLstatement_dev, but none of those methods but setPropVals is implemented in query_dev. All abstract methods from base classes have to be implemented in the class to be instantiated.
I implemented dummy-methods for the unimplemented methods which solved the "abstract-issue".

More Answers (1)

Daniel Shub
Daniel Shub on 16 Aug 2011
There is a lot of code but it looks like SQLstatement_dev defines the abstract methods assembleStatement, submitStatement, setPropVals, and getPropVals. These are passed down behind the scenes to query_dev. The query_dev class defines setPropVals, but not assembleStatement, submitStatement, and getPropVals. You need to define those abstract methods in query_dev.
  5 Comments
David Goldsmith
David Goldsmith on 16 Aug 2011
Thanks, guys. (Ah, the foibles of having a Biblical name that begins w/ Da, right Daniel?) ;-)
I understood/knew that about Abstract/derived classes; what I didn't understand was that if you weren't yet ready to write the definition of an Abstract method in a derived class, but had its declaration in your parent class (as a design reminder, say), then you would get an error complaining about the derived class being an Abstract class, which, IMO, is worse than unhelpful, in that it's, quite literally, misleading (again, IMO).
Matlab Developers: if you see this, may I humbly suggest changing the error message in this situation to something a little more helpful, e.g., "Class <DC>, derived from Abstract class <AC>, requires definitions for Abstract method(s) X (Y, Z, etc.), but none were found." Indeed, it seems to me that this is something that M-Lint could find and offer to fix (by insertion of "stubs" for the missing methods, e.g.)... (I'd say "just a thought," but I really feel more strongly than that about it: please do it!)
Thanks again, P and D!
Daniel Shub
Daniel Shub on 17 Aug 2011
The chances that the Mathworks sees this are greatly increased if you submit it to them as a product enhancement. I don't see a reason the error message could not be improved. I doubt mlint could detect this. Mlint does not know about the superclass properties and methods, if the superclass is not on the path while you are editing the subclass.

Sign in to comment.

Categories

Find more on Software Development Tools in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!